mvc-kit 2.12.4 → 2.13.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 (186) hide show
  1. package/agent-config/bin/postinstall.mjs +4 -3
  2. package/agent-config/bin/setup.mjs +5 -1
  3. package/agent-config/claude-code/agents/mvc-kit-architect.md +11 -8
  4. package/agent-config/claude-code/skills/guide/SKILL.md +20 -7
  5. package/agent-config/claude-code/skills/guide/patterns.md +12 -0
  6. package/agent-config/claude-code/skills/guide/recipes.md +510 -0
  7. package/agent-config/claude-code/skills/guide/testing.md +297 -0
  8. package/agent-config/claude-code/skills/review/SKILL.md +3 -13
  9. package/agent-config/claude-code/skills/review/checklist.md +30 -5
  10. package/agent-config/claude-code/skills/scaffold/SKILL.md +4 -13
  11. package/agent-config/lib/install-claude.mjs +84 -25
  12. package/dist/Channel.cjs +276 -300
  13. package/dist/Channel.cjs.map +1 -1
  14. package/dist/Channel.js +275 -299
  15. package/dist/Channel.js.map +1 -1
  16. package/dist/Collection.cjs +424 -504
  17. package/dist/Collection.cjs.map +1 -1
  18. package/dist/Collection.js +423 -503
  19. package/dist/Collection.js.map +1 -1
  20. package/dist/Controller.cjs +70 -67
  21. package/dist/Controller.cjs.map +1 -1
  22. package/dist/Controller.js +69 -66
  23. package/dist/Controller.js.map +1 -1
  24. package/dist/EventBus.cjs +77 -88
  25. package/dist/EventBus.cjs.map +1 -1
  26. package/dist/EventBus.js +76 -87
  27. package/dist/EventBus.js.map +1 -1
  28. package/dist/Feed.cjs +81 -77
  29. package/dist/Feed.cjs.map +1 -1
  30. package/dist/Feed.js +80 -76
  31. package/dist/Feed.js.map +1 -1
  32. package/dist/Model.cjs +181 -207
  33. package/dist/Model.cjs.map +1 -1
  34. package/dist/Model.js +179 -205
  35. package/dist/Model.js.map +1 -1
  36. package/dist/Pagination.cjs +75 -73
  37. package/dist/Pagination.cjs.map +1 -1
  38. package/dist/Pagination.js +74 -72
  39. package/dist/Pagination.js.map +1 -1
  40. package/dist/Pending.cjs +255 -287
  41. package/dist/Pending.cjs.map +1 -1
  42. package/dist/Pending.js +253 -285
  43. package/dist/Pending.js.map +1 -1
  44. package/dist/PersistentCollection.cjs +242 -285
  45. package/dist/PersistentCollection.cjs.map +1 -1
  46. package/dist/PersistentCollection.js +241 -284
  47. package/dist/PersistentCollection.js.map +1 -1
  48. package/dist/Resource.cjs +166 -174
  49. package/dist/Resource.cjs.map +1 -1
  50. package/dist/Resource.js +164 -172
  51. package/dist/Resource.js.map +1 -1
  52. package/dist/Selection.cjs +84 -94
  53. package/dist/Selection.cjs.map +1 -1
  54. package/dist/Selection.js +83 -93
  55. package/dist/Selection.js.map +1 -1
  56. package/dist/Service.cjs +54 -55
  57. package/dist/Service.cjs.map +1 -1
  58. package/dist/Service.js +53 -54
  59. package/dist/Service.js.map +1 -1
  60. package/dist/Sorting.cjs +102 -101
  61. package/dist/Sorting.cjs.map +1 -1
  62. package/dist/Sorting.js +102 -101
  63. package/dist/Sorting.js.map +1 -1
  64. package/dist/Trackable.cjs +112 -80
  65. package/dist/Trackable.cjs.map +1 -1
  66. package/dist/Trackable.js +111 -79
  67. package/dist/Trackable.js.map +1 -1
  68. package/dist/ViewModel.cjs +528 -576
  69. package/dist/ViewModel.cjs.map +1 -1
  70. package/dist/ViewModel.js +525 -573
  71. package/dist/ViewModel.js.map +1 -1
  72. package/dist/bindPublicMethods.cjs +43 -24
  73. package/dist/bindPublicMethods.cjs.map +1 -1
  74. package/dist/bindPublicMethods.js +43 -24
  75. package/dist/bindPublicMethods.js.map +1 -1
  76. package/dist/errors.cjs +67 -68
  77. package/dist/errors.cjs.map +1 -1
  78. package/dist/errors.js +68 -71
  79. package/dist/errors.js.map +1 -1
  80. package/dist/mvc-kit.cjs +44 -46
  81. package/dist/mvc-kit.js +5 -32
  82. package/dist/produceDraft.cjs +105 -95
  83. package/dist/produceDraft.cjs.map +1 -1
  84. package/dist/produceDraft.js +106 -97
  85. package/dist/produceDraft.js.map +1 -1
  86. package/dist/react/components/CardList.cjs +30 -40
  87. package/dist/react/components/CardList.cjs.map +1 -1
  88. package/dist/react/components/CardList.js +31 -41
  89. package/dist/react/components/CardList.js.map +1 -1
  90. package/dist/react/components/DataTable.cjs +146 -169
  91. package/dist/react/components/DataTable.cjs.map +1 -1
  92. package/dist/react/components/DataTable.js +147 -170
  93. package/dist/react/components/DataTable.js.map +1 -1
  94. package/dist/react/components/InfiniteScroll.cjs +51 -42
  95. package/dist/react/components/InfiniteScroll.cjs.map +1 -1
  96. package/dist/react/components/InfiniteScroll.js +52 -43
  97. package/dist/react/components/InfiniteScroll.js.map +1 -1
  98. package/dist/react/components/types.cjs +10 -6
  99. package/dist/react/components/types.cjs.map +1 -1
  100. package/dist/react/components/types.js +11 -9
  101. package/dist/react/components/types.js.map +1 -1
  102. package/dist/react/guards.cjs +10 -6
  103. package/dist/react/guards.cjs.map +1 -1
  104. package/dist/react/guards.js +11 -9
  105. package/dist/react/guards.js.map +1 -1
  106. package/dist/react/provider.cjs +23 -20
  107. package/dist/react/provider.cjs.map +1 -1
  108. package/dist/react/provider.js +23 -21
  109. package/dist/react/provider.js.map +1 -1
  110. package/dist/react/use-event-bus.cjs +24 -20
  111. package/dist/react/use-event-bus.cjs.map +1 -1
  112. package/dist/react/use-event-bus.js +24 -21
  113. package/dist/react/use-event-bus.js.map +1 -1
  114. package/dist/react/use-instance.cjs +43 -36
  115. package/dist/react/use-instance.cjs.map +1 -1
  116. package/dist/react/use-instance.js +43 -36
  117. package/dist/react/use-instance.js.map +1 -1
  118. package/dist/react/use-local.cjs +48 -64
  119. package/dist/react/use-local.cjs.map +1 -1
  120. package/dist/react/use-local.js +47 -63
  121. package/dist/react/use-local.js.map +1 -1
  122. package/dist/react/use-model.cjs +84 -98
  123. package/dist/react/use-model.cjs.map +1 -1
  124. package/dist/react/use-model.js +84 -100
  125. package/dist/react/use-model.js.map +1 -1
  126. package/dist/react/use-singleton.cjs +19 -23
  127. package/dist/react/use-singleton.cjs.map +1 -1
  128. package/dist/react/use-singleton.js +16 -20
  129. package/dist/react/use-singleton.js.map +1 -1
  130. package/dist/react/use-subscribe-only.cjs +28 -22
  131. package/dist/react/use-subscribe-only.cjs.map +1 -1
  132. package/dist/react/use-subscribe-only.js +28 -22
  133. package/dist/react/use-subscribe-only.js.map +1 -1
  134. package/dist/react/use-teardown.cjs +20 -19
  135. package/dist/react/use-teardown.cjs.map +1 -1
  136. package/dist/react/use-teardown.js +20 -19
  137. package/dist/react/use-teardown.js.map +1 -1
  138. package/dist/react-native/NativeCollection.cjs +98 -78
  139. package/dist/react-native/NativeCollection.cjs.map +1 -1
  140. package/dist/react-native/NativeCollection.js +97 -77
  141. package/dist/react-native/NativeCollection.js.map +1 -1
  142. package/dist/react-native.cjs +2 -4
  143. package/dist/react-native.js +1 -4
  144. package/dist/react.cjs +24 -26
  145. package/dist/react.js +1 -17
  146. package/dist/singleton.cjs +28 -22
  147. package/dist/singleton.cjs.map +1 -1
  148. package/dist/singleton.js +29 -26
  149. package/dist/singleton.js.map +1 -1
  150. package/dist/walkPrototypeChain.cjs +20 -12
  151. package/dist/walkPrototypeChain.cjs.map +1 -1
  152. package/dist/walkPrototypeChain.js +21 -13
  153. package/dist/walkPrototypeChain.js.map +1 -1
  154. package/dist/web/IndexedDBCollection.cjs +53 -36
  155. package/dist/web/IndexedDBCollection.cjs.map +1 -1
  156. package/dist/web/IndexedDBCollection.js +52 -35
  157. package/dist/web/IndexedDBCollection.js.map +1 -1
  158. package/dist/web/WebStorageCollection.cjs +82 -84
  159. package/dist/web/WebStorageCollection.cjs.map +1 -1
  160. package/dist/web/WebStorageCollection.js +81 -83
  161. package/dist/web/WebStorageCollection.js.map +1 -1
  162. package/dist/web/idb.cjs +107 -99
  163. package/dist/web/idb.cjs.map +1 -1
  164. package/dist/web/idb.js +108 -105
  165. package/dist/web/idb.js.map +1 -1
  166. package/dist/web.cjs +4 -6
  167. package/dist/web.js +1 -5
  168. package/dist/wrapAsyncMethods.cjs +141 -168
  169. package/dist/wrapAsyncMethods.cjs.map +1 -1
  170. package/dist/wrapAsyncMethods.js +141 -168
  171. package/dist/wrapAsyncMethods.js.map +1 -1
  172. package/package.json +8 -8
  173. package/src/Pending.test.ts +1 -2
  174. package/src/Sorting.test.ts +1 -1
  175. package/src/produceDraft.test.ts +3 -3
  176. package/src/react/components/CardList.test.tsx +1 -1
  177. package/src/react/components/DataTable.test.tsx +1 -1
  178. package/src/react/components/InfiniteScroll.test.tsx +5 -5
  179. package/dist/mvc-kit.cjs.map +0 -1
  180. package/dist/mvc-kit.js.map +0 -1
  181. package/dist/react-native.cjs.map +0 -1
  182. package/dist/react-native.js.map +0 -1
  183. package/dist/react.cjs.map +0 -1
  184. package/dist/react.js.map +0 -1
  185. package/dist/web.cjs.map +0 -1
  186. package/dist/web.js.map +0 -1
@@ -1,81 +1,113 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const bindPublicMethods = require("./bindPublicMethods.cjs");
4
- const PROTECTED_KEYS = /* @__PURE__ */ new Set(["addCleanup", "notify"]);
5
- class Trackable {
6
- _listeners = null;
7
- _disposed = false;
8
- _abortController = null;
9
- _cleanups = null;
10
- constructor() {
11
- bindPublicMethods.bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);
12
- }
13
- // ── Disposable interface ──
14
- /** Whether this instance has been disposed. */
15
- get disposed() {
16
- return this._disposed;
17
- }
18
- /** AbortSignal that fires when this instance is disposed. Lazily created. */
19
- get disposeSignal() {
20
- if (!this._abortController) {
21
- this._abortController = new AbortController();
22
- }
23
- return this._abortController.signal;
24
- }
25
- /**
26
- * Tear down the instance: abort the dispose signal, run all registered
27
- * cleanups, clear subscribers, and call onDispose. Idempotent.
28
- */
29
- dispose() {
30
- if (this._disposed) return;
31
- this._disposed = true;
32
- this._abortController?.abort();
33
- if (this._cleanups) {
34
- for (const fn of this._cleanups) fn();
35
- this._cleanups = null;
36
- }
37
- this._listeners?.clear();
38
- this.onDispose?.();
39
- }
40
- // ── Subscribable (notification-only, no state) ──
41
- /**
42
- * Subscribe to change notifications. The callback is invoked (with no
43
- * arguments) whenever the subclass calls {@link notify}.
44
- *
45
- * This is the duck-typed contract that ViewModel's auto-tracking system
46
- * recognizes — any object with a `subscribe` method is automatically
47
- * tracked when accessed inside a ViewModel getter.
48
- *
49
- * @returns An unsubscribe function.
50
- */
51
- subscribe(cb) {
52
- if (!this._listeners) this._listeners = /* @__PURE__ */ new Set();
53
- this._listeners.add(cb);
54
- return () => {
55
- this._listeners?.delete(cb);
56
- };
57
- }
58
- /**
59
- * Notify all subscribers that state has changed. Call this after
60
- * mutating internal state to trigger ViewModel getter invalidation
61
- * and React re-renders.
62
- * @protected
63
- */
64
- notify() {
65
- if (this._listeners) {
66
- for (const cb of this._listeners) cb();
67
- }
68
- }
69
- // ── Protected utilities ──
70
- /**
71
- * Register a cleanup function to be called on {@link dispose}.
72
- * Cleanups run in registration order.
73
- * @protected
74
- */
75
- addCleanup(fn) {
76
- if (!this._cleanups) this._cleanups = [];
77
- this._cleanups.push(fn);
78
- }
79
- }
1
+ const require_bindPublicMethods = require("./bindPublicMethods.cjs");
2
+ //#region src/Trackable.ts
3
+ var PROTECTED_KEYS = new Set(["addCleanup", "notify"]);
4
+ /**
5
+ * Base class for custom reactive objects that integrate with ViewModel's
6
+ * auto-tracking system. Provides subscribable notifications, disposal
7
+ * lifecycle, and automatic method binding.
8
+ *
9
+ * Any object with a `subscribe()` method is auto-tracked by ViewModel
10
+ * getters. Trackable gives you that plus cleanup infrastructure and
11
+ * point-free methods — the same building blocks used by Sorting,
12
+ * Selection, Feed, Pagination, and Pending.
13
+ *
14
+ * Use Trackable when integrating third-party SDKs, custom query objects,
15
+ * or any reactive state that doesn't fit ViewModel's state/getter model.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * class RPCQuery<Data> extends Trackable {
20
+ * private _data: Data | undefined;
21
+ * private _loading = false;
22
+ *
23
+ * get data() { return this._data; }
24
+ * get loading() { return this._loading; }
25
+ *
26
+ * async call(): Promise<void> {
27
+ * this._loading = true;
28
+ * this.notify();
29
+ * this._data = await fetchData();
30
+ * this._loading = false;
31
+ * this.notify();
32
+ * }
33
+ * }
34
+ *
35
+ * // Used as a ViewModel property — auto-tracked:
36
+ * class UsersVM extends ViewModel {
37
+ * readonly users = new RPCQuery<User[]>();
38
+ * get userList() { return this.users.data ?? []; }
39
+ * }
40
+ * ```
41
+ */
42
+ var Trackable = class {
43
+ _listeners = null;
44
+ _disposed = false;
45
+ _abortController = null;
46
+ _cleanups = null;
47
+ constructor() {
48
+ require_bindPublicMethods.bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);
49
+ }
50
+ /** Whether this instance has been disposed. */
51
+ get disposed() {
52
+ return this._disposed;
53
+ }
54
+ /** AbortSignal that fires when this instance is disposed. Lazily created. */
55
+ get disposeSignal() {
56
+ if (!this._abortController) this._abortController = new AbortController();
57
+ return this._abortController.signal;
58
+ }
59
+ /**
60
+ * Tear down the instance: abort the dispose signal, run all registered
61
+ * cleanups, clear subscribers, and call onDispose. Idempotent.
62
+ */
63
+ dispose() {
64
+ if (this._disposed) return;
65
+ this._disposed = true;
66
+ this._abortController?.abort();
67
+ if (this._cleanups) {
68
+ for (const fn of this._cleanups) fn();
69
+ this._cleanups = null;
70
+ }
71
+ this._listeners?.clear();
72
+ this.onDispose?.();
73
+ }
74
+ /**
75
+ * Subscribe to change notifications. The callback is invoked (with no
76
+ * arguments) whenever the subclass calls {@link notify}.
77
+ *
78
+ * This is the duck-typed contract that ViewModel's auto-tracking system
79
+ * recognizes — any object with a `subscribe` method is automatically
80
+ * tracked when accessed inside a ViewModel getter.
81
+ *
82
+ * @returns An unsubscribe function.
83
+ */
84
+ subscribe(cb) {
85
+ if (!this._listeners) this._listeners = /* @__PURE__ */ new Set();
86
+ this._listeners.add(cb);
87
+ return () => {
88
+ this._listeners?.delete(cb);
89
+ };
90
+ }
91
+ /**
92
+ * Notify all subscribers that state has changed. Call this after
93
+ * mutating internal state to trigger ViewModel getter invalidation
94
+ * and React re-renders.
95
+ * @protected
96
+ */
97
+ notify() {
98
+ if (this._listeners) for (const cb of this._listeners) cb();
99
+ }
100
+ /**
101
+ * Register a cleanup function to be called on {@link dispose}.
102
+ * Cleanups run in registration order.
103
+ * @protected
104
+ */
105
+ addCleanup(fn) {
106
+ if (!this._cleanups) this._cleanups = [];
107
+ this._cleanups.push(fn);
108
+ }
109
+ };
110
+ //#endregion
80
111
  exports.Trackable = Trackable;
81
- //# sourceMappingURL=Trackable.cjs.map
112
+
113
+ //# sourceMappingURL=Trackable.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Trackable.cjs","sources":["../src/Trackable.ts"],"sourcesContent":["import type { Disposable } from './types';\nimport { bindPublicMethods } from './bindPublicMethods';\n\nconst PROTECTED_KEYS = new Set(['addCleanup', 'notify']);\n\n/**\n * Base class for custom reactive objects that integrate with ViewModel's\n * auto-tracking system. Provides subscribable notifications, disposal\n * lifecycle, and automatic method binding.\n *\n * Any object with a `subscribe()` method is auto-tracked by ViewModel\n * getters. Trackable gives you that plus cleanup infrastructure and\n * point-free methods — the same building blocks used by Sorting,\n * Selection, Feed, Pagination, and Pending.\n *\n * Use Trackable when integrating third-party SDKs, custom query objects,\n * or any reactive state that doesn't fit ViewModel's state/getter model.\n *\n * @example\n * ```ts\n * class RPCQuery<Data> extends Trackable {\n * private _data: Data | undefined;\n * private _loading = false;\n *\n * get data() { return this._data; }\n * get loading() { return this._loading; }\n *\n * async call(): Promise<void> {\n * this._loading = true;\n * this.notify();\n * this._data = await fetchData();\n * this._loading = false;\n * this.notify();\n * }\n * }\n *\n * // Used as a ViewModel property — auto-tracked:\n * class UsersVM extends ViewModel {\n * readonly users = new RPCQuery<User[]>();\n * get userList() { return this.users.data ?? []; }\n * }\n * ```\n */\nexport class Trackable implements Disposable {\n private _listeners: Set<() => void> | null = null;\n private _disposed = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n constructor() {\n bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);\n }\n\n // ── Disposable interface ──\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** AbortSignal that fires when this instance is disposed. Lazily created. */\n get disposeSignal(): AbortSignal {\n if (!this._abortController) {\n this._abortController = new AbortController();\n }\n return this._abortController.signal;\n }\n\n /**\n * Tear down the instance: abort the dispose signal, run all registered\n * cleanups, clear subscribers, and call onDispose. Idempotent.\n */\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._abortController?.abort();\n if (this._cleanups) {\n for (const fn of this._cleanups) fn();\n this._cleanups = null;\n }\n this._listeners?.clear();\n this.onDispose?.();\n }\n\n // ── Subscribable (notification-only, no state) ──\n\n /**\n * Subscribe to change notifications. The callback is invoked (with no\n * arguments) whenever the subclass calls {@link notify}.\n *\n * This is the duck-typed contract that ViewModel's auto-tracking system\n * recognizes — any object with a `subscribe` method is automatically\n * tracked when accessed inside a ViewModel getter.\n *\n * @returns An unsubscribe function.\n */\n subscribe(cb: () => void): () => void {\n if (!this._listeners) this._listeners = new Set();\n this._listeners.add(cb);\n return () => { this._listeners?.delete(cb); };\n }\n\n /**\n * Notify all subscribers that state has changed. Call this after\n * mutating internal state to trigger ViewModel getter invalidation\n * and React re-renders.\n * @protected\n */\n protected notify(): void {\n if (this._listeners) {\n for (const cb of this._listeners) cb();\n }\n }\n\n // ── Protected utilities ──\n\n /**\n * Register a cleanup function to be called on {@link dispose}.\n * Cleanups run in registration order.\n * @protected\n */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) this._cleanups = [];\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"names":["bindPublicMethods"],"mappings":";;;AAGA,MAAM,iBAAiB,oBAAI,IAAI,CAAC,cAAc,QAAQ,CAAC;AAwChD,MAAM,UAAgC;AAAA,EACnC,aAAqC;AAAA,EACrC,YAAY;AAAA,EACZ,mBAA2C;AAAA,EAC3C,YAAmC;AAAA,EAE3C,cAAc;AACZA,sBAAAA,kBAAkB,MAAM,OAAO,WAAW,cAAc;AAAA,EAC1D;AAAA;AAAA;AAAA,EAKA,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,gBAA6B;AAC/B,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,mBAAmB,IAAI,gBAAA;AAAA,IAC9B;AACA,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACd,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AACjB,SAAK,kBAAkB,MAAA;AACvB,QAAI,KAAK,WAAW;AAClB,iBAAW,MAAM,KAAK,UAAW,IAAA;AACjC,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,YAAY,MAAA;AACjB,SAAK,YAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UAAU,IAA4B;AACpC,QAAI,CAAC,KAAK,WAAY,MAAK,iCAAiB,IAAA;AAC5C,SAAK,WAAW,IAAI,EAAE;AACtB,WAAO,MAAM;AAAE,WAAK,YAAY,OAAO,EAAE;AAAA,IAAG;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,SAAe;AACvB,QAAI,KAAK,YAAY;AACnB,iBAAW,MAAM,KAAK,WAAY,IAAA;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,WAAW,IAAsB;AACzC,QAAI,CAAC,KAAK,UAAW,MAAK,YAAY,CAAA;AACtC,SAAK,UAAU,KAAK,EAAE;AAAA,EACxB;AAIF;;"}
1
+ {"version":3,"file":"Trackable.cjs","names":[],"sources":["../src/Trackable.ts"],"sourcesContent":["import type { Disposable } from './types';\nimport { bindPublicMethods } from './bindPublicMethods';\n\nconst PROTECTED_KEYS = new Set(['addCleanup', 'notify']);\n\n/**\n * Base class for custom reactive objects that integrate with ViewModel's\n * auto-tracking system. Provides subscribable notifications, disposal\n * lifecycle, and automatic method binding.\n *\n * Any object with a `subscribe()` method is auto-tracked by ViewModel\n * getters. Trackable gives you that plus cleanup infrastructure and\n * point-free methods — the same building blocks used by Sorting,\n * Selection, Feed, Pagination, and Pending.\n *\n * Use Trackable when integrating third-party SDKs, custom query objects,\n * or any reactive state that doesn't fit ViewModel's state/getter model.\n *\n * @example\n * ```ts\n * class RPCQuery<Data> extends Trackable {\n * private _data: Data | undefined;\n * private _loading = false;\n *\n * get data() { return this._data; }\n * get loading() { return this._loading; }\n *\n * async call(): Promise<void> {\n * this._loading = true;\n * this.notify();\n * this._data = await fetchData();\n * this._loading = false;\n * this.notify();\n * }\n * }\n *\n * // Used as a ViewModel property — auto-tracked:\n * class UsersVM extends ViewModel {\n * readonly users = new RPCQuery<User[]>();\n * get userList() { return this.users.data ?? []; }\n * }\n * ```\n */\nexport class Trackable implements Disposable {\n private _listeners: Set<() => void> | null = null;\n private _disposed = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n constructor() {\n bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);\n }\n\n // ── Disposable interface ──\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** AbortSignal that fires when this instance is disposed. Lazily created. */\n get disposeSignal(): AbortSignal {\n if (!this._abortController) {\n this._abortController = new AbortController();\n }\n return this._abortController.signal;\n }\n\n /**\n * Tear down the instance: abort the dispose signal, run all registered\n * cleanups, clear subscribers, and call onDispose. Idempotent.\n */\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._abortController?.abort();\n if (this._cleanups) {\n for (const fn of this._cleanups) fn();\n this._cleanups = null;\n }\n this._listeners?.clear();\n this.onDispose?.();\n }\n\n // ── Subscribable (notification-only, no state) ──\n\n /**\n * Subscribe to change notifications. The callback is invoked (with no\n * arguments) whenever the subclass calls {@link notify}.\n *\n * This is the duck-typed contract that ViewModel's auto-tracking system\n * recognizes — any object with a `subscribe` method is automatically\n * tracked when accessed inside a ViewModel getter.\n *\n * @returns An unsubscribe function.\n */\n subscribe(cb: () => void): () => void {\n if (!this._listeners) this._listeners = new Set();\n this._listeners.add(cb);\n return () => { this._listeners?.delete(cb); };\n }\n\n /**\n * Notify all subscribers that state has changed. Call this after\n * mutating internal state to trigger ViewModel getter invalidation\n * and React re-renders.\n * @protected\n */\n protected notify(): void {\n if (this._listeners) {\n for (const cb of this._listeners) cb();\n }\n }\n\n // ── Protected utilities ──\n\n /**\n * Register a cleanup function to be called on {@link dispose}.\n * Cleanups run in registration order.\n * @protected\n */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) this._cleanups = [];\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"mappings":";;AAGA,IAAM,iBAAiB,IAAI,IAAI,CAAC,cAAc,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCxD,IAAa,YAAb,MAA6C;CAC3C,aAA6C;CAC7C,YAAoB;CACpB,mBAAmD;CACnD,YAA2C;CAE3C,cAAc;AACZ,4BAAA,kBAAkB,MAAM,OAAO,WAAW,eAAe;;;CAM3D,IAAI,WAAoB;AACtB,SAAO,KAAK;;;CAId,IAAI,gBAA6B;AAC/B,MAAI,CAAC,KAAK,iBACR,MAAK,mBAAmB,IAAI,iBAAiB;AAE/C,SAAO,KAAK,iBAAiB;;;;;;CAO/B,UAAgB;AACd,MAAI,KAAK,UAAW;AACpB,OAAK,YAAY;AACjB,OAAK,kBAAkB,OAAO;AAC9B,MAAI,KAAK,WAAW;AAClB,QAAK,MAAM,MAAM,KAAK,UAAW,KAAI;AACrC,QAAK,YAAY;;AAEnB,OAAK,YAAY,OAAO;AACxB,OAAK,aAAa;;;;;;;;;;;;CAepB,UAAU,IAA4B;AACpC,MAAI,CAAC,KAAK,WAAY,MAAK,6BAAa,IAAI,KAAK;AACjD,OAAK,WAAW,IAAI,GAAG;AACvB,eAAa;AAAE,QAAK,YAAY,OAAO,GAAG;;;;;;;;;CAS5C,SAAyB;AACvB,MAAI,KAAK,WACP,MAAK,MAAM,MAAM,KAAK,WAAY,KAAI;;;;;;;CAW1C,WAAqB,IAAsB;AACzC,MAAI,CAAC,KAAK,UAAW,MAAK,YAAY,EAAE;AACxC,OAAK,UAAU,KAAK,GAAG"}
package/dist/Trackable.js CHANGED
@@ -1,81 +1,113 @@
1
1
  import { bindPublicMethods } from "./bindPublicMethods.js";
2
- const PROTECTED_KEYS = /* @__PURE__ */ new Set(["addCleanup", "notify"]);
3
- class Trackable {
4
- _listeners = null;
5
- _disposed = false;
6
- _abortController = null;
7
- _cleanups = null;
8
- constructor() {
9
- bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);
10
- }
11
- // ── Disposable interface ──
12
- /** Whether this instance has been disposed. */
13
- get disposed() {
14
- return this._disposed;
15
- }
16
- /** AbortSignal that fires when this instance is disposed. Lazily created. */
17
- get disposeSignal() {
18
- if (!this._abortController) {
19
- this._abortController = new AbortController();
20
- }
21
- return this._abortController.signal;
22
- }
23
- /**
24
- * Tear down the instance: abort the dispose signal, run all registered
25
- * cleanups, clear subscribers, and call onDispose. Idempotent.
26
- */
27
- dispose() {
28
- if (this._disposed) return;
29
- this._disposed = true;
30
- this._abortController?.abort();
31
- if (this._cleanups) {
32
- for (const fn of this._cleanups) fn();
33
- this._cleanups = null;
34
- }
35
- this._listeners?.clear();
36
- this.onDispose?.();
37
- }
38
- // ── Subscribable (notification-only, no state) ──
39
- /**
40
- * Subscribe to change notifications. The callback is invoked (with no
41
- * arguments) whenever the subclass calls {@link notify}.
42
- *
43
- * This is the duck-typed contract that ViewModel's auto-tracking system
44
- * recognizes — any object with a `subscribe` method is automatically
45
- * tracked when accessed inside a ViewModel getter.
46
- *
47
- * @returns An unsubscribe function.
48
- */
49
- subscribe(cb) {
50
- if (!this._listeners) this._listeners = /* @__PURE__ */ new Set();
51
- this._listeners.add(cb);
52
- return () => {
53
- this._listeners?.delete(cb);
54
- };
55
- }
56
- /**
57
- * Notify all subscribers that state has changed. Call this after
58
- * mutating internal state to trigger ViewModel getter invalidation
59
- * and React re-renders.
60
- * @protected
61
- */
62
- notify() {
63
- if (this._listeners) {
64
- for (const cb of this._listeners) cb();
65
- }
66
- }
67
- // ── Protected utilities ──
68
- /**
69
- * Register a cleanup function to be called on {@link dispose}.
70
- * Cleanups run in registration order.
71
- * @protected
72
- */
73
- addCleanup(fn) {
74
- if (!this._cleanups) this._cleanups = [];
75
- this._cleanups.push(fn);
76
- }
77
- }
78
- export {
79
- Trackable
2
+ //#region src/Trackable.ts
3
+ var PROTECTED_KEYS = new Set(["addCleanup", "notify"]);
4
+ /**
5
+ * Base class for custom reactive objects that integrate with ViewModel's
6
+ * auto-tracking system. Provides subscribable notifications, disposal
7
+ * lifecycle, and automatic method binding.
8
+ *
9
+ * Any object with a `subscribe()` method is auto-tracked by ViewModel
10
+ * getters. Trackable gives you that plus cleanup infrastructure and
11
+ * point-free methods the same building blocks used by Sorting,
12
+ * Selection, Feed, Pagination, and Pending.
13
+ *
14
+ * Use Trackable when integrating third-party SDKs, custom query objects,
15
+ * or any reactive state that doesn't fit ViewModel's state/getter model.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * class RPCQuery<Data> extends Trackable {
20
+ * private _data: Data | undefined;
21
+ * private _loading = false;
22
+ *
23
+ * get data() { return this._data; }
24
+ * get loading() { return this._loading; }
25
+ *
26
+ * async call(): Promise<void> {
27
+ * this._loading = true;
28
+ * this.notify();
29
+ * this._data = await fetchData();
30
+ * this._loading = false;
31
+ * this.notify();
32
+ * }
33
+ * }
34
+ *
35
+ * // Used as a ViewModel property — auto-tracked:
36
+ * class UsersVM extends ViewModel {
37
+ * readonly users = new RPCQuery<User[]>();
38
+ * get userList() { return this.users.data ?? []; }
39
+ * }
40
+ * ```
41
+ */
42
+ var Trackable = class {
43
+ _listeners = null;
44
+ _disposed = false;
45
+ _abortController = null;
46
+ _cleanups = null;
47
+ constructor() {
48
+ bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);
49
+ }
50
+ /** Whether this instance has been disposed. */
51
+ get disposed() {
52
+ return this._disposed;
53
+ }
54
+ /** AbortSignal that fires when this instance is disposed. Lazily created. */
55
+ get disposeSignal() {
56
+ if (!this._abortController) this._abortController = new AbortController();
57
+ return this._abortController.signal;
58
+ }
59
+ /**
60
+ * Tear down the instance: abort the dispose signal, run all registered
61
+ * cleanups, clear subscribers, and call onDispose. Idempotent.
62
+ */
63
+ dispose() {
64
+ if (this._disposed) return;
65
+ this._disposed = true;
66
+ this._abortController?.abort();
67
+ if (this._cleanups) {
68
+ for (const fn of this._cleanups) fn();
69
+ this._cleanups = null;
70
+ }
71
+ this._listeners?.clear();
72
+ this.onDispose?.();
73
+ }
74
+ /**
75
+ * Subscribe to change notifications. The callback is invoked (with no
76
+ * arguments) whenever the subclass calls {@link notify}.
77
+ *
78
+ * This is the duck-typed contract that ViewModel's auto-tracking system
79
+ * recognizes — any object with a `subscribe` method is automatically
80
+ * tracked when accessed inside a ViewModel getter.
81
+ *
82
+ * @returns An unsubscribe function.
83
+ */
84
+ subscribe(cb) {
85
+ if (!this._listeners) this._listeners = /* @__PURE__ */ new Set();
86
+ this._listeners.add(cb);
87
+ return () => {
88
+ this._listeners?.delete(cb);
89
+ };
90
+ }
91
+ /**
92
+ * Notify all subscribers that state has changed. Call this after
93
+ * mutating internal state to trigger ViewModel getter invalidation
94
+ * and React re-renders.
95
+ * @protected
96
+ */
97
+ notify() {
98
+ if (this._listeners) for (const cb of this._listeners) cb();
99
+ }
100
+ /**
101
+ * Register a cleanup function to be called on {@link dispose}.
102
+ * Cleanups run in registration order.
103
+ * @protected
104
+ */
105
+ addCleanup(fn) {
106
+ if (!this._cleanups) this._cleanups = [];
107
+ this._cleanups.push(fn);
108
+ }
80
109
  };
81
- //# sourceMappingURL=Trackable.js.map
110
+ //#endregion
111
+ export { Trackable };
112
+
113
+ //# sourceMappingURL=Trackable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Trackable.js","sources":["../src/Trackable.ts"],"sourcesContent":["import type { Disposable } from './types';\nimport { bindPublicMethods } from './bindPublicMethods';\n\nconst PROTECTED_KEYS = new Set(['addCleanup', 'notify']);\n\n/**\n * Base class for custom reactive objects that integrate with ViewModel's\n * auto-tracking system. Provides subscribable notifications, disposal\n * lifecycle, and automatic method binding.\n *\n * Any object with a `subscribe()` method is auto-tracked by ViewModel\n * getters. Trackable gives you that plus cleanup infrastructure and\n * point-free methods — the same building blocks used by Sorting,\n * Selection, Feed, Pagination, and Pending.\n *\n * Use Trackable when integrating third-party SDKs, custom query objects,\n * or any reactive state that doesn't fit ViewModel's state/getter model.\n *\n * @example\n * ```ts\n * class RPCQuery<Data> extends Trackable {\n * private _data: Data | undefined;\n * private _loading = false;\n *\n * get data() { return this._data; }\n * get loading() { return this._loading; }\n *\n * async call(): Promise<void> {\n * this._loading = true;\n * this.notify();\n * this._data = await fetchData();\n * this._loading = false;\n * this.notify();\n * }\n * }\n *\n * // Used as a ViewModel property — auto-tracked:\n * class UsersVM extends ViewModel {\n * readonly users = new RPCQuery<User[]>();\n * get userList() { return this.users.data ?? []; }\n * }\n * ```\n */\nexport class Trackable implements Disposable {\n private _listeners: Set<() => void> | null = null;\n private _disposed = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n constructor() {\n bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);\n }\n\n // ── Disposable interface ──\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** AbortSignal that fires when this instance is disposed. Lazily created. */\n get disposeSignal(): AbortSignal {\n if (!this._abortController) {\n this._abortController = new AbortController();\n }\n return this._abortController.signal;\n }\n\n /**\n * Tear down the instance: abort the dispose signal, run all registered\n * cleanups, clear subscribers, and call onDispose. Idempotent.\n */\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._abortController?.abort();\n if (this._cleanups) {\n for (const fn of this._cleanups) fn();\n this._cleanups = null;\n }\n this._listeners?.clear();\n this.onDispose?.();\n }\n\n // ── Subscribable (notification-only, no state) ──\n\n /**\n * Subscribe to change notifications. The callback is invoked (with no\n * arguments) whenever the subclass calls {@link notify}.\n *\n * This is the duck-typed contract that ViewModel's auto-tracking system\n * recognizes — any object with a `subscribe` method is automatically\n * tracked when accessed inside a ViewModel getter.\n *\n * @returns An unsubscribe function.\n */\n subscribe(cb: () => void): () => void {\n if (!this._listeners) this._listeners = new Set();\n this._listeners.add(cb);\n return () => { this._listeners?.delete(cb); };\n }\n\n /**\n * Notify all subscribers that state has changed. Call this after\n * mutating internal state to trigger ViewModel getter invalidation\n * and React re-renders.\n * @protected\n */\n protected notify(): void {\n if (this._listeners) {\n for (const cb of this._listeners) cb();\n }\n }\n\n // ── Protected utilities ──\n\n /**\n * Register a cleanup function to be called on {@link dispose}.\n * Cleanups run in registration order.\n * @protected\n */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) this._cleanups = [];\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"names":[],"mappings":";AAGA,MAAM,iBAAiB,oBAAI,IAAI,CAAC,cAAc,QAAQ,CAAC;AAwChD,MAAM,UAAgC;AAAA,EACnC,aAAqC;AAAA,EACrC,YAAY;AAAA,EACZ,mBAA2C;AAAA,EAC3C,YAAmC;AAAA,EAE3C,cAAc;AACZ,sBAAkB,MAAM,OAAO,WAAW,cAAc;AAAA,EAC1D;AAAA;AAAA;AAAA,EAKA,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,gBAA6B;AAC/B,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,mBAAmB,IAAI,gBAAA;AAAA,IAC9B;AACA,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACd,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AACjB,SAAK,kBAAkB,MAAA;AACvB,QAAI,KAAK,WAAW;AAClB,iBAAW,MAAM,KAAK,UAAW,IAAA;AACjC,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,YAAY,MAAA;AACjB,SAAK,YAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UAAU,IAA4B;AACpC,QAAI,CAAC,KAAK,WAAY,MAAK,iCAAiB,IAAA;AAC5C,SAAK,WAAW,IAAI,EAAE;AACtB,WAAO,MAAM;AAAE,WAAK,YAAY,OAAO,EAAE;AAAA,IAAG;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,SAAe;AACvB,QAAI,KAAK,YAAY;AACnB,iBAAW,MAAM,KAAK,WAAY,IAAA;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,WAAW,IAAsB;AACzC,QAAI,CAAC,KAAK,UAAW,MAAK,YAAY,CAAA;AACtC,SAAK,UAAU,KAAK,EAAE;AAAA,EACxB;AAIF;"}
1
+ {"version":3,"file":"Trackable.js","names":[],"sources":["../src/Trackable.ts"],"sourcesContent":["import type { Disposable } from './types';\nimport { bindPublicMethods } from './bindPublicMethods';\n\nconst PROTECTED_KEYS = new Set(['addCleanup', 'notify']);\n\n/**\n * Base class for custom reactive objects that integrate with ViewModel's\n * auto-tracking system. Provides subscribable notifications, disposal\n * lifecycle, and automatic method binding.\n *\n * Any object with a `subscribe()` method is auto-tracked by ViewModel\n * getters. Trackable gives you that plus cleanup infrastructure and\n * point-free methods — the same building blocks used by Sorting,\n * Selection, Feed, Pagination, and Pending.\n *\n * Use Trackable when integrating third-party SDKs, custom query objects,\n * or any reactive state that doesn't fit ViewModel's state/getter model.\n *\n * @example\n * ```ts\n * class RPCQuery<Data> extends Trackable {\n * private _data: Data | undefined;\n * private _loading = false;\n *\n * get data() { return this._data; }\n * get loading() { return this._loading; }\n *\n * async call(): Promise<void> {\n * this._loading = true;\n * this.notify();\n * this._data = await fetchData();\n * this._loading = false;\n * this.notify();\n * }\n * }\n *\n * // Used as a ViewModel property — auto-tracked:\n * class UsersVM extends ViewModel {\n * readonly users = new RPCQuery<User[]>();\n * get userList() { return this.users.data ?? []; }\n * }\n * ```\n */\nexport class Trackable implements Disposable {\n private _listeners: Set<() => void> | null = null;\n private _disposed = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n constructor() {\n bindPublicMethods(this, Object.prototype, PROTECTED_KEYS);\n }\n\n // ── Disposable interface ──\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** AbortSignal that fires when this instance is disposed. Lazily created. */\n get disposeSignal(): AbortSignal {\n if (!this._abortController) {\n this._abortController = new AbortController();\n }\n return this._abortController.signal;\n }\n\n /**\n * Tear down the instance: abort the dispose signal, run all registered\n * cleanups, clear subscribers, and call onDispose. Idempotent.\n */\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._abortController?.abort();\n if (this._cleanups) {\n for (const fn of this._cleanups) fn();\n this._cleanups = null;\n }\n this._listeners?.clear();\n this.onDispose?.();\n }\n\n // ── Subscribable (notification-only, no state) ──\n\n /**\n * Subscribe to change notifications. The callback is invoked (with no\n * arguments) whenever the subclass calls {@link notify}.\n *\n * This is the duck-typed contract that ViewModel's auto-tracking system\n * recognizes — any object with a `subscribe` method is automatically\n * tracked when accessed inside a ViewModel getter.\n *\n * @returns An unsubscribe function.\n */\n subscribe(cb: () => void): () => void {\n if (!this._listeners) this._listeners = new Set();\n this._listeners.add(cb);\n return () => { this._listeners?.delete(cb); };\n }\n\n /**\n * Notify all subscribers that state has changed. Call this after\n * mutating internal state to trigger ViewModel getter invalidation\n * and React re-renders.\n * @protected\n */\n protected notify(): void {\n if (this._listeners) {\n for (const cb of this._listeners) cb();\n }\n }\n\n // ── Protected utilities ──\n\n /**\n * Register a cleanup function to be called on {@link dispose}.\n * Cleanups run in registration order.\n * @protected\n */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) this._cleanups = [];\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"mappings":";;AAGA,IAAM,iBAAiB,IAAI,IAAI,CAAC,cAAc,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCxD,IAAa,YAAb,MAA6C;CAC3C,aAA6C;CAC7C,YAAoB;CACpB,mBAAmD;CACnD,YAA2C;CAE3C,cAAc;AACZ,oBAAkB,MAAM,OAAO,WAAW,eAAe;;;CAM3D,IAAI,WAAoB;AACtB,SAAO,KAAK;;;CAId,IAAI,gBAA6B;AAC/B,MAAI,CAAC,KAAK,iBACR,MAAK,mBAAmB,IAAI,iBAAiB;AAE/C,SAAO,KAAK,iBAAiB;;;;;;CAO/B,UAAgB;AACd,MAAI,KAAK,UAAW;AACpB,OAAK,YAAY;AACjB,OAAK,kBAAkB,OAAO;AAC9B,MAAI,KAAK,WAAW;AAClB,QAAK,MAAM,MAAM,KAAK,UAAW,KAAI;AACrC,QAAK,YAAY;;AAEnB,OAAK,YAAY,OAAO;AACxB,OAAK,aAAa;;;;;;;;;;;;CAepB,UAAU,IAA4B;AACpC,MAAI,CAAC,KAAK,WAAY,MAAK,6BAAa,IAAI,KAAK;AACjD,OAAK,WAAW,IAAI,GAAG;AACvB,eAAa;AAAE,QAAK,YAAY,OAAO,GAAG;;;;;;;;;CAS5C,SAAyB;AACvB,MAAI,KAAK,WACP,MAAK,MAAM,MAAM,KAAK,WAAY,KAAI;;;;;;;CAW1C,WAAqB,IAAsB;AACzC,MAAI,CAAC,KAAK,UAAW,MAAK,YAAY,EAAE;AACxC,OAAK,UAAU,KAAK,GAAG"}