mvc-kit 2.5.3 → 2.5.4

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 (125) hide show
  1. package/dist/Channel.cjs +291 -0
  2. package/dist/Channel.cjs.map +1 -0
  3. package/dist/Channel.js +291 -0
  4. package/dist/Channel.js.map +1 -0
  5. package/dist/Collection.cjs +452 -0
  6. package/dist/Collection.cjs.map +1 -0
  7. package/dist/Collection.js +452 -0
  8. package/dist/Collection.js.map +1 -0
  9. package/dist/Controller.cjs +57 -0
  10. package/dist/Controller.cjs.map +1 -0
  11. package/dist/Controller.js +57 -0
  12. package/dist/Controller.js.map +1 -0
  13. package/dist/EventBus.cjs +84 -0
  14. package/dist/EventBus.cjs.map +1 -0
  15. package/dist/EventBus.js +84 -0
  16. package/dist/EventBus.js.map +1 -0
  17. package/dist/Model.cjs +175 -0
  18. package/dist/Model.cjs.map +1 -0
  19. package/dist/Model.js +175 -0
  20. package/dist/Model.js.map +1 -0
  21. package/dist/PersistentCollection.cjs +285 -0
  22. package/dist/PersistentCollection.cjs.map +1 -0
  23. package/dist/PersistentCollection.js +285 -0
  24. package/dist/PersistentCollection.js.map +1 -0
  25. package/dist/Resource.cjs +308 -0
  26. package/dist/Resource.cjs.map +1 -0
  27. package/dist/Resource.js +308 -0
  28. package/dist/Resource.js.map +1 -0
  29. package/dist/Service.cjs +51 -0
  30. package/dist/Service.cjs.map +1 -0
  31. package/dist/Service.js +51 -0
  32. package/dist/Service.js.map +1 -0
  33. package/dist/ViewModel.cjs +582 -0
  34. package/dist/ViewModel.cjs.map +1 -0
  35. package/dist/ViewModel.d.ts +1 -7
  36. package/dist/ViewModel.d.ts.map +1 -1
  37. package/dist/ViewModel.js +582 -0
  38. package/dist/ViewModel.js.map +1 -0
  39. package/dist/errors.cjs +79 -0
  40. package/dist/errors.cjs.map +1 -0
  41. package/dist/errors.js +79 -0
  42. package/dist/errors.js.map +1 -0
  43. package/dist/mvc-kit.cjs +29 -1
  44. package/dist/mvc-kit.cjs.map +1 -1
  45. package/dist/mvc-kit.js +27 -1132
  46. package/dist/mvc-kit.js.map +1 -1
  47. package/dist/react/guards.cjs +7 -0
  48. package/dist/react/guards.cjs.map +1 -0
  49. package/dist/react/guards.js +7 -0
  50. package/dist/react/guards.js.map +1 -0
  51. package/dist/react/provider.cjs +26 -0
  52. package/dist/react/provider.cjs.map +1 -0
  53. package/dist/react/provider.js +26 -0
  54. package/dist/react/provider.js.map +1 -0
  55. package/dist/react/use-event-bus.cjs +26 -0
  56. package/dist/react/use-event-bus.cjs.map +1 -0
  57. package/dist/react/use-event-bus.js +26 -0
  58. package/dist/react/use-event-bus.js.map +1 -0
  59. package/dist/react/use-instance.cjs +31 -0
  60. package/dist/react/use-instance.cjs.map +1 -0
  61. package/dist/react/use-instance.js +31 -0
  62. package/dist/react/use-instance.js.map +1 -0
  63. package/dist/react/use-local.cjs +64 -0
  64. package/dist/react/use-local.cjs.map +1 -0
  65. package/dist/react/use-local.js +64 -0
  66. package/dist/react/use-local.js.map +1 -0
  67. package/dist/react/use-model.cjs +80 -0
  68. package/dist/react/use-model.cjs.map +1 -0
  69. package/dist/react/use-model.js +80 -0
  70. package/dist/react/use-model.js.map +1 -0
  71. package/dist/react/use-singleton.cjs +21 -0
  72. package/dist/react/use-singleton.cjs.map +1 -0
  73. package/dist/react/use-singleton.js +21 -0
  74. package/dist/react/use-singleton.js.map +1 -0
  75. package/dist/react/use-teardown.cjs +22 -0
  76. package/dist/react/use-teardown.cjs.map +1 -0
  77. package/dist/react/use-teardown.js +22 -0
  78. package/dist/react/use-teardown.js.map +1 -0
  79. package/dist/react-native/NativeCollection.cjs +76 -0
  80. package/dist/react-native/NativeCollection.cjs.map +1 -0
  81. package/dist/react-native/NativeCollection.js +76 -0
  82. package/dist/react-native/NativeCollection.js.map +1 -0
  83. package/dist/react-native.cjs +4 -1
  84. package/dist/react-native.cjs.map +1 -1
  85. package/dist/react-native.js +2 -60
  86. package/dist/react-native.js.map +1 -1
  87. package/dist/react.cjs +19 -1
  88. package/dist/react.cjs.map +1 -1
  89. package/dist/react.js +17 -145
  90. package/dist/react.js.map +1 -1
  91. package/dist/singleton.cjs +34 -0
  92. package/dist/singleton.cjs.map +1 -0
  93. package/dist/singleton.js +34 -0
  94. package/dist/singleton.js.map +1 -0
  95. package/dist/walkPrototypeChain.cjs +15 -0
  96. package/dist/walkPrototypeChain.cjs.map +1 -0
  97. package/dist/walkPrototypeChain.d.ts +9 -0
  98. package/dist/walkPrototypeChain.d.ts.map +1 -0
  99. package/dist/walkPrototypeChain.js +15 -0
  100. package/dist/walkPrototypeChain.js.map +1 -0
  101. package/dist/web/IndexedDBCollection.cjs +37 -0
  102. package/dist/web/IndexedDBCollection.cjs.map +1 -0
  103. package/dist/web/IndexedDBCollection.js +37 -0
  104. package/dist/web/IndexedDBCollection.js.map +1 -0
  105. package/dist/web/WebStorageCollection.cjs +85 -0
  106. package/dist/web/WebStorageCollection.cjs.map +1 -0
  107. package/dist/web/WebStorageCollection.js +85 -0
  108. package/dist/web/WebStorageCollection.js.map +1 -0
  109. package/dist/web/idb.cjs +121 -0
  110. package/dist/web/idb.cjs.map +1 -0
  111. package/dist/web/idb.js +121 -0
  112. package/dist/web/idb.js.map +1 -0
  113. package/dist/web.cjs +6 -1
  114. package/dist/web.cjs.map +1 -1
  115. package/dist/web.js +4 -178
  116. package/dist/web.js.map +1 -1
  117. package/package.json +4 -2
  118. package/dist/PersistentCollection-B8kNECDj.cjs +0 -2
  119. package/dist/PersistentCollection-B8kNECDj.cjs.map +0 -1
  120. package/dist/PersistentCollection-CbYqzFHc.js +0 -542
  121. package/dist/PersistentCollection-CbYqzFHc.js.map +0 -1
  122. package/dist/singleton-CaEXSbYg.js +0 -89
  123. package/dist/singleton-CaEXSbYg.js.map +0 -1
  124. package/dist/singleton-L-u2W_lX.cjs +0 -2
  125. package/dist/singleton-L-u2W_lX.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Resource.js","sources":["../src/Resource.ts"],"sourcesContent":["import { Collection } from './Collection';\nimport { walkPrototypeChain } from './walkPrototypeChain';\nimport { isAbortError, classifyError } from './errors';\nimport type { Listener, TaskState } from './types';\n\nconst __DEV__ = typeof __MVC_KIT_DEV__ !== 'undefined' && __MVC_KIT_DEV__;\n\n// ── Async tracking types ────────────────────────────────────────\n\nconst DEFAULT_TASK_STATE: TaskState = Object.freeze({ loading: false, error: null, errorCode: null });\n\nexport type ResourceAsyncMethodKeys<T> = {\n [K in Exclude<keyof T, keyof Resource<any>>]: T[K] extends (...args: any[]) => Promise<any> ? K : never;\n}[Exclude<keyof T, keyof Resource<any>>];\n\ntype ResourceAsyncMap<T> = {\n readonly [K in ResourceAsyncMethodKeys<T>]: TaskState;\n};\n\ninterface InternalTaskState {\n loading: boolean;\n error: string | null;\n errorCode: TaskState['errorCode'];\n count: number;\n}\n\nconst RESERVED_ASYNC_KEYS = ['async', 'subscribeAsync'] as const;\nconst LIFECYCLE_HOOKS = new Set(['onInit', 'onDispose']);\n\n// ── Resource ────────────────────────────────────────────────────\n\n/**\n * Collection + async tracking toolkit. Extends Collection with lifecycle\n * (init/dispose) and automatic async method tracking. Optionally delegates\n * to an external Collection for shared data scenarios.\n */\nexport class Resource<T extends { id: string | number }> extends Collection<T> {\n private _external: Collection<T> | null = null;\n private _initialized = false;\n\n // ── Async tracking fields ──\n private _asyncStates = new Map<string, InternalTaskState>();\n private _asyncSnapshots = new Map<string, TaskState>();\n private _asyncListeners = new Set<() => void>();\n private _asyncProxy: ResourceAsyncMap<this> | null = null;\n private _activeOps: Map<string, number> | null = null;\n\n /** DEV-only timeout (ms) for detecting ghost async operations after dispose. */\n static GHOST_TIMEOUT = 3000;\n\n constructor(collectionOrItems?: Collection<T> | T[]) {\n const isExternal = collectionOrItems != null && !Array.isArray(collectionOrItems);\n super(isExternal ? [] : (collectionOrItems as T[]) ?? []);\n\n if (isExternal) {\n this._external = collectionOrItems as Collection<T>;\n\n if (__DEV__) {\n const Ctor = this.constructor as typeof Resource;\n if (Ctor.MAX_SIZE > 0 || Ctor.TTL > 0) {\n console.warn(\n `[mvc-kit] Resource \"${Ctor.name}\" has MAX_SIZE or TTL set but uses an ` +\n `injected Collection. Configure these on the Collection instead.`\n );\n }\n }\n }\n\n this._guardReservedKeys();\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────\n\n /** Whether init() has been called. */\n get initialized(): boolean {\n return this._initialized;\n }\n\n /** Initializes the instance. Called automatically by React hooks after mount. */\n init(): void | Promise<void> {\n if (this._initialized || this.disposed) return;\n this._initialized = true;\n this._wrapMethods();\n return this.onInit?.();\n }\n\n /** Lifecycle hook called at the end of init(). Override to load initial data. @protected */\n protected onInit?(): void | Promise<void>;\n\n // ── Collection delegation ─────────────────────────────────────\n\n get state(): T[] {\n return this._external ? this._external.state : super.state;\n }\n\n get items(): T[] {\n return this._external ? this._external.items : super.items;\n }\n\n get length(): number {\n return this._external ? this._external.length : super.length;\n }\n\n add(...items: T[]): void {\n this._external ? this._external.add(...items) : super.add(...items);\n }\n\n upsert(...items: T[]): void {\n this._external ? this._external.upsert(...items) : super.upsert(...items);\n }\n\n update(id: T['id'], changes: Partial<T>): void {\n this._external ? this._external.update(id, changes) : super.update(id, changes);\n }\n\n remove(...ids: T['id'][]): void {\n this._external ? this._external.remove(...ids) : super.remove(...ids);\n }\n\n reset(items: T[]): void {\n this._external ? this._external.reset(items) : super.reset(items);\n }\n\n clear(): void {\n this._external ? this._external.clear() : super.clear();\n }\n\n optimistic(callback: () => void): () => void {\n return this._external ? this._external.optimistic(callback) : super.optimistic(callback);\n }\n\n get(id: T['id']): T | undefined {\n return this._external ? this._external.get(id) : super.get(id);\n }\n\n has(id: T['id']): boolean {\n return this._external ? this._external.has(id) : super.has(id);\n }\n\n find(predicate: (item: T) => boolean): T | undefined {\n return this._external ? this._external.find(predicate) : super.find(predicate);\n }\n\n filter(predicate: (item: T) => boolean): T[] {\n return this._external ? this._external.filter(predicate) : super.filter(predicate);\n }\n\n sorted(compareFn: (a: T, b: T) => number): T[] {\n return this._external ? this._external.sorted(compareFn) : super.sorted(compareFn);\n }\n\n map<U>(fn: (item: T) => U): U[] {\n return this._external ? this._external.map(fn) : super.map(fn);\n }\n\n subscribe(listener: Listener<T[]>): () => void {\n if (this.disposed) return () => {};\n return this._external ? this._external.subscribe(listener) : super.subscribe(listener);\n }\n\n // ── Async tracking API ────────────────────────────────────────\n\n /** Proxy providing `TaskState` (loading, error, errorCode) per async method. */\n get async(): ResourceAsyncMap<this> {\n if (!this._asyncProxy) {\n const self = this;\n this._asyncProxy = new Proxy({} as ResourceAsyncMap<this>, {\n get(_, prop: string) {\n return self._asyncSnapshots.get(prop) ?? DEFAULT_TASK_STATE;\n },\n has(_, prop: string) {\n return self._asyncSnapshots.has(prop);\n },\n ownKeys() {\n return Array.from(self._asyncSnapshots.keys());\n },\n getOwnPropertyDescriptor(_, prop: string) {\n if (self._asyncSnapshots.has(prop)) {\n return { configurable: true, enumerable: true, value: self._asyncSnapshots.get(prop) };\n }\n return undefined;\n },\n });\n }\n return this._asyncProxy;\n }\n\n /** Subscribes to async state changes. Used by `useAsync` and `useInstance` for React integration. */\n subscribeAsync(listener: () => void): () => void {\n if (this.disposed) return () => {};\n this._asyncListeners.add(listener);\n return () => { this._asyncListeners.delete(listener); };\n }\n\n // ── Private: async tracking internals ─────────────────────────\n\n private _notifyAsync(): void {\n for (const listener of this._asyncListeners) {\n listener();\n }\n }\n\n private _guardReservedKeys(): void {\n walkPrototypeChain(this, Resource.prototype, (key) => {\n if (RESERVED_ASYNC_KEYS.includes(key as any)) {\n throw new Error(\n `[mvc-kit] \"${key}\" is a reserved property on Resource and cannot be overridden.`\n );\n }\n });\n }\n\n private _wrapMethods(): void {\n // Instance property check (class fields assigned after super())\n for (const key of RESERVED_ASYNC_KEYS) {\n if (Object.getOwnPropertyDescriptor(this, key)?.value !== undefined) {\n throw new Error(\n `[mvc-kit] \"${key}\" is a reserved property on Resource and cannot be overridden.`\n );\n }\n }\n\n const self = this;\n const processed = new Set<string>();\n const wrappedKeys: string[] = [];\n\n if (__DEV__) {\n this._activeOps = new Map();\n }\n\n walkPrototypeChain(this, Resource.prototype, (key, desc) => {\n // Skip getters/setters\n if (desc.get || desc.set) return;\n // Skip non-functions\n if (typeof desc.value !== 'function') return;\n // Skip _-prefixed (private convention)\n if (key.startsWith('_')) return;\n // Skip lifecycle hooks (managed by framework)\n if (LIFECYCLE_HOOKS.has(key)) return;\n // Most-derived wins\n if (processed.has(key)) return;\n processed.add(key);\n\n const original = desc.value as (...args: unknown[]) => unknown;\n let pruned = false;\n\n const wrapper = function (this: any, ...args: unknown[]) {\n // Disposed guard\n if (self.disposed) {\n if (__DEV__) {\n console.warn(`[mvc-kit] \"${key}\" called after dispose — ignored.`);\n }\n return undefined;\n }\n\n // Pre-init guard (DEV only — method still executes)\n if (__DEV__ && !self._initialized) {\n console.warn(\n `[mvc-kit] \"${key}\" called before init(). ` +\n `Async tracking is active only after init().`\n );\n }\n\n let result: unknown;\n try {\n result = original.apply(self, args);\n } catch (e) {\n // Sync throw — not tracked as async\n throw e;\n }\n\n // Sync detection: if not thenable, prune from async tracking\n if (!result || typeof (result as any).then !== 'function') {\n if (!pruned) {\n pruned = true;\n // Remove from async maps\n self._asyncStates.delete(key);\n self._asyncSnapshots.delete(key);\n // Replace wrapper with bound original for zero overhead\n (self as any)[key] = original.bind(self);\n }\n return result;\n }\n\n // ── Async tracking ──────────────────────────────────────\n let internal = self._asyncStates.get(key);\n if (!internal) {\n internal = { loading: false, error: null, errorCode: null, count: 0 };\n self._asyncStates.set(key, internal);\n }\n\n internal.count++;\n internal.loading = true;\n internal.error = null;\n internal.errorCode = null;\n self._asyncSnapshots.set(key, Object.freeze({ loading: true, error: null, errorCode: null }));\n self._notifyAsync();\n\n if (__DEV__ && self._activeOps) {\n self._activeOps.set(key, (self._activeOps.get(key) ?? 0) + 1);\n }\n\n return (result as Promise<unknown>).then(\n (value) => {\n if (self.disposed) return value;\n\n internal!.count--;\n internal!.loading = internal!.count > 0;\n self._asyncSnapshots.set(\n key,\n Object.freeze({ loading: internal!.loading, error: internal!.error, errorCode: internal!.errorCode }),\n );\n self._notifyAsync();\n\n if (__DEV__ && self._activeOps) {\n const c = (self._activeOps.get(key) ?? 1) - 1;\n if (c <= 0) self._activeOps.delete(key);\n else self._activeOps.set(key, c);\n }\n\n return value;\n },\n (error) => {\n // AbortError — silently swallow\n if (isAbortError(error)) {\n if (!self.disposed) {\n internal!.count--;\n internal!.loading = internal!.count > 0;\n self._asyncSnapshots.set(\n key,\n Object.freeze({ loading: internal!.loading, error: internal!.error, errorCode: internal!.errorCode }),\n );\n self._notifyAsync();\n }\n\n if (__DEV__ && self._activeOps) {\n const c = (self._activeOps.get(key) ?? 1) - 1;\n if (c <= 0) self._activeOps.delete(key);\n else self._activeOps.set(key, c);\n }\n\n return undefined;\n }\n\n // Disposed — fizzle silently\n if (self.disposed) return undefined;\n\n internal!.count--;\n internal!.loading = internal!.count > 0;\n const classified = classifyError(error);\n internal!.error = classified.message;\n internal!.errorCode = classified.code;\n self._asyncSnapshots.set(\n key,\n Object.freeze({ loading: internal!.loading, error: classified.message, errorCode: classified.code }),\n );\n self._notifyAsync();\n\n if (__DEV__ && self._activeOps) {\n const c = (self._activeOps.get(key) ?? 1) - 1;\n if (c <= 0) self._activeOps.delete(key);\n else self._activeOps.set(key, c);\n }\n\n // Re-throw to preserve standard Promise rejection\n throw error;\n },\n );\n };\n\n wrappedKeys.push(key);\n (self as any)[key] = wrapper;\n });\n\n // Register cleanup for disposal\n if (wrappedKeys.length > 0) {\n this.addCleanup(() => {\n // Snapshot active ops for ghost check before clearing\n const opsSnapshot = __DEV__ && self._activeOps ? new Map(self._activeOps) : null;\n\n // Swap all wrapped methods to no-ops (with DEV warning)\n for (const k of wrappedKeys) {\n if (__DEV__) {\n (self as any)[k] = () => {\n console.warn(`[mvc-kit] \"${k}\" called after dispose — ignored.`);\n return undefined;\n };\n } else {\n (self as any)[k] = () => undefined;\n }\n }\n\n // Clear async state\n self._asyncListeners.clear();\n self._asyncStates.clear();\n self._asyncSnapshots.clear();\n\n // DEV: schedule ghost check\n if (__DEV__ && opsSnapshot && opsSnapshot.size > 0) {\n self._scheduleGhostCheck(opsSnapshot);\n }\n });\n }\n }\n\n private _scheduleGhostCheck(opsSnapshot: Map<string, number>): void {\n if (!__DEV__) return;\n setTimeout(() => {\n for (const [key, count] of opsSnapshot) {\n console.warn(\n `[mvc-kit] Ghost async operation detected: \"${key}\" had ${count} ` +\n `pending call(s) when the Resource was disposed. ` +\n `Consider using disposeSignal to cancel in-flight work.`\n );\n }\n }, (this.constructor as typeof Resource).GHOST_TIMEOUT);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ class Service {
4
+ _disposed = false;
5
+ _initialized = false;
6
+ _abortController = null;
7
+ _cleanups = null;
8
+ /** Whether this instance has been disposed. */
9
+ get disposed() {
10
+ return this._disposed;
11
+ }
12
+ /** Whether init() has been called. */
13
+ get initialized() {
14
+ return this._initialized;
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
+ /** Initializes the instance. Called automatically by React hooks after mount. */
24
+ init() {
25
+ if (this._initialized || this._disposed) return;
26
+ this._initialized = true;
27
+ return this.onInit?.();
28
+ }
29
+ /** Tears down the instance, releasing all subscriptions and resources. */
30
+ dispose() {
31
+ if (this._disposed) {
32
+ return;
33
+ }
34
+ this._disposed = true;
35
+ this._abortController?.abort();
36
+ if (this._cleanups) {
37
+ for (const fn of this._cleanups) fn();
38
+ this._cleanups = null;
39
+ }
40
+ this.onDispose?.();
41
+ }
42
+ /** Registers a cleanup function to be called on dispose. @protected */
43
+ addCleanup(fn) {
44
+ if (!this._cleanups) {
45
+ this._cleanups = [];
46
+ }
47
+ this._cleanups.push(fn);
48
+ }
49
+ }
50
+ exports.Service = Service;
51
+ //# sourceMappingURL=Service.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Service.cjs","sources":["../src/Service.ts"],"sourcesContent":["import type { Disposable } from './types';\n\n/**\n * Base class for non-reactive infrastructure services.\n * Services encapsulate external dependencies like APIs, storage, etc.\n */\nexport abstract class Service implements Disposable {\n private _disposed = false;\n private _initialized = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** Whether init() has been called. */\n get initialized(): boolean {\n return this._initialized;\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 /** Initializes the instance. Called automatically by React hooks after mount. */\n init(): void | Promise<void> {\n if (this._initialized || this._disposed) return;\n this._initialized = true;\n return this.onInit?.();\n }\n\n /** Tears down the instance, releasing all subscriptions and resources. */\n dispose(): void {\n if (this._disposed) {\n return;\n }\n\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.onDispose?.();\n }\n\n /** Registers a cleanup function to be called on dispose. @protected */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) {\n this._cleanups = [];\n }\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of init(). Override to load initial data. @protected */\n protected onInit?(): void | Promise<void>;\n /** Lifecycle hook called during dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"names":[],"mappings":";;AAMO,MAAe,QAA8B;AAAA,EAC1C,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAA2C;AAAA,EAC3C,YAAmC;AAAA;AAAA,EAG3C,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,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,EAGA,OAA6B;AAC3B,QAAI,KAAK,gBAAgB,KAAK,UAAW;AACzC,SAAK,eAAe;AACpB,WAAO,KAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AAEA,SAAK,YAAY;AACjB,SAAK,kBAAkB,MAAA;AACvB,QAAI,KAAK,WAAW;AAClB,iBAAW,MAAM,KAAK,UAAW,IAAA;AACjC,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,YAAA;AAAA,EACP;AAAA;AAAA,EAGU,WAAW,IAAsB;AACzC,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY,CAAA;AAAA,IACnB;AACA,SAAK,UAAU,KAAK,EAAE;AAAA,EACxB;AAMF;;"}
@@ -0,0 +1,51 @@
1
+ class Service {
2
+ _disposed = false;
3
+ _initialized = false;
4
+ _abortController = null;
5
+ _cleanups = null;
6
+ /** Whether this instance has been disposed. */
7
+ get disposed() {
8
+ return this._disposed;
9
+ }
10
+ /** Whether init() has been called. */
11
+ get initialized() {
12
+ return this._initialized;
13
+ }
14
+ /** AbortSignal that fires when this instance is disposed. Lazily created. */
15
+ get disposeSignal() {
16
+ if (!this._abortController) {
17
+ this._abortController = new AbortController();
18
+ }
19
+ return this._abortController.signal;
20
+ }
21
+ /** Initializes the instance. Called automatically by React hooks after mount. */
22
+ init() {
23
+ if (this._initialized || this._disposed) return;
24
+ this._initialized = true;
25
+ return this.onInit?.();
26
+ }
27
+ /** Tears down the instance, releasing all subscriptions and resources. */
28
+ dispose() {
29
+ if (this._disposed) {
30
+ return;
31
+ }
32
+ this._disposed = true;
33
+ this._abortController?.abort();
34
+ if (this._cleanups) {
35
+ for (const fn of this._cleanups) fn();
36
+ this._cleanups = null;
37
+ }
38
+ this.onDispose?.();
39
+ }
40
+ /** Registers a cleanup function to be called on dispose. @protected */
41
+ addCleanup(fn) {
42
+ if (!this._cleanups) {
43
+ this._cleanups = [];
44
+ }
45
+ this._cleanups.push(fn);
46
+ }
47
+ }
48
+ export {
49
+ Service
50
+ };
51
+ //# sourceMappingURL=Service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Service.js","sources":["../src/Service.ts"],"sourcesContent":["import type { Disposable } from './types';\n\n/**\n * Base class for non-reactive infrastructure services.\n * Services encapsulate external dependencies like APIs, storage, etc.\n */\nexport abstract class Service implements Disposable {\n private _disposed = false;\n private _initialized = false;\n private _abortController: AbortController | null = null;\n private _cleanups: (() => void)[] | null = null;\n\n /** Whether this instance has been disposed. */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /** Whether init() has been called. */\n get initialized(): boolean {\n return this._initialized;\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 /** Initializes the instance. Called automatically by React hooks after mount. */\n init(): void | Promise<void> {\n if (this._initialized || this._disposed) return;\n this._initialized = true;\n return this.onInit?.();\n }\n\n /** Tears down the instance, releasing all subscriptions and resources. */\n dispose(): void {\n if (this._disposed) {\n return;\n }\n\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.onDispose?.();\n }\n\n /** Registers a cleanup function to be called on dispose. @protected */\n protected addCleanup(fn: () => void): void {\n if (!this._cleanups) {\n this._cleanups = [];\n }\n this._cleanups.push(fn);\n }\n\n /** Lifecycle hook called at the end of init(). Override to load initial data. @protected */\n protected onInit?(): void | Promise<void>;\n /** Lifecycle hook called during dispose(). Override for custom teardown. @protected */\n protected onDispose?(): void;\n}\n"],"names":[],"mappings":"AAMO,MAAe,QAA8B;AAAA,EAC1C,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAA2C;AAAA,EAC3C,YAAmC;AAAA;AAAA,EAG3C,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,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,EAGA,OAA6B;AAC3B,QAAI,KAAK,gBAAgB,KAAK,UAAW;AACzC,SAAK,eAAe;AACpB,WAAO,KAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AAEA,SAAK,YAAY;AACjB,SAAK,kBAAkB,MAAA;AACvB,QAAI,KAAK,WAAW;AAClB,iBAAW,MAAM,KAAK,UAAW,IAAA;AACjC,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,YAAA;AAAA,EACP;AAAA;AAAA,EAGU,WAAW,IAAsB;AACzC,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY,CAAA;AAAA,IACnB;AACA,SAAK,UAAU,KAAK,EAAE;AAAA,EACxB;AAMF;"}