@adobe/data 0.9.7 → 0.9.16

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 (310) hide show
  1. package/data.d.ts +1 -1
  2. package/ecs/database/combine-plugins.d.ts +14 -7
  3. package/ecs/database/combine-plugins.js +6 -3
  4. package/ecs/database/combine-plugins.js.map +1 -1
  5. package/ecs/database/create-plugin.d.ts +37 -17
  6. package/ecs/database/create-plugin.js +3 -30
  7. package/ecs/database/create-plugin.js.map +1 -1
  8. package/ecs/database/create-plugin.test.js +55 -0
  9. package/ecs/database/create-plugin.test.js.map +1 -1
  10. package/ecs/database/create-plugin.type-test.js +157 -0
  11. package/ecs/database/create-plugin.type-test.js.map +1 -1
  12. package/ecs/database/database-schema/create-database-schema.js +3 -3
  13. package/ecs/database/database-schema/create-database-schema.js.map +1 -1
  14. package/ecs/database/database.d.ts +43 -5
  15. package/ecs/database/database.js.map +1 -1
  16. package/ecs/database/observe-dependent-value.test.js +39 -31
  17. package/ecs/database/observe-dependent-value.test.js.map +1 -1
  18. package/ecs/database/observe-select-entities.performance.test.js +30 -31
  19. package/ecs/database/observe-select-entities.performance.test.js.map +1 -1
  20. package/ecs/database/observe-select-entities.test.js +30 -31
  21. package/ecs/database/observe-select-entities.test.js.map +1 -1
  22. package/ecs/database/observed/create-observed-database.js +7 -0
  23. package/ecs/database/observed/create-observed-database.js.map +1 -1
  24. package/ecs/database/public/create-database.d.ts +5 -34
  25. package/ecs/database/public/create-database.js +68 -131
  26. package/ecs/database/public/create-database.js.map +1 -1
  27. package/ecs/database/public/create-database.test.js +324 -62
  28. package/ecs/database/public/create-database.test.js.map +1 -1
  29. package/ecs/database/transactional-store/create-transactional-store.js +16 -1
  30. package/ecs/database/transactional-store/create-transactional-store.js.map +1 -1
  31. package/ecs/plugins/scheduler/scheduler.d.ts +2 -2
  32. package/ecs/plugins/scheduler/scheduler.js +2 -2
  33. package/ecs/plugins/scheduler/scheduler.js.map +1 -1
  34. package/ecs/undo-redo-service/create-undo-redo-service.test.js +22 -23
  35. package/ecs/undo-redo-service/create-undo-redo-service.test.js.map +1 -1
  36. package/package.json +6 -24
  37. package/service/async-data-service/create-lazy.d.ts +40 -0
  38. package/service/async-data-service/create-lazy.js +194 -0
  39. package/service/async-data-service/create-lazy.js.map +1 -0
  40. package/service/async-data-service/create-lazy.test.js +477 -0
  41. package/service/async-data-service/create-lazy.test.js.map +1 -0
  42. package/service/async-data-service/example.d.ts +60 -0
  43. package/service/async-data-service/example.js +35 -0
  44. package/service/async-data-service/example.js.map +1 -0
  45. package/service/async-data-service/index.d.ts +1 -0
  46. package/service/async-data-service/index.js +3 -0
  47. package/service/async-data-service/index.js.map +1 -0
  48. package/service/{is-data-service.d.ts → async-data-service/is-valid.d.ts} +4 -4
  49. package/{lit/hooks/component/component.js → service/async-data-service/is-valid.js} +1 -1
  50. package/service/async-data-service/is-valid.js.map +1 -0
  51. package/service/async-data-service/public.d.ts +2 -0
  52. package/service/async-data-service/public.js +4 -0
  53. package/service/async-data-service/public.js.map +1 -0
  54. package/service/index.d.ts +1 -1
  55. package/service/index.js +1 -0
  56. package/service/index.js.map +1 -1
  57. package/tsconfig.tsbuildinfo +1 -1
  58. package/ecs/database/combine-plugins-test.d.ts +0 -39
  59. package/ecs/database/combine-plugins-test.js +0 -3
  60. package/ecs/database/combine-plugins-test.js.map +0 -1
  61. package/ecs/database/create-plugin-cryos-pattern.test.d.ts +0 -3
  62. package/ecs/database/create-plugin-cryos-pattern.test.js +0 -83
  63. package/ecs/database/create-plugin-cryos-pattern.test.js.map +0 -1
  64. package/ecs/database/create-plugin-graphics.test.d.ts +0 -93
  65. package/ecs/database/create-plugin-graphics.test.js +0 -135
  66. package/ecs/database/create-plugin-graphics.test.js.map +0 -1
  67. package/ecs/database/create-plugin-type.type-test.js +0 -563
  68. package/ecs/database/create-plugin-type.type-test.js.map +0 -1
  69. package/ecs/database/create-plugin-type.type.test.d.ts +0 -1
  70. package/ecs/database/create-plugin-type.type.test.js +0 -563
  71. package/ecs/database/create-plugin-type.type.test.js.map +0 -1
  72. package/ecs/database/experimental-action-types.d.ts +0 -1
  73. package/ecs/database/experimental-action-types.js +0 -275
  74. package/ecs/database/experimental-action-types.js.map +0 -1
  75. package/ecs/database/from-plugin.type-test.d.ts +0 -1
  76. package/ecs/database/from-plugin.type-test.js +0 -180
  77. package/ecs/database/from-plugin.type-test.js.map +0 -1
  78. package/ecs/database/plugin-types.d.ts +0 -1
  79. package/ecs/database/plugin-types.js +0 -5
  80. package/ecs/database/plugin-types.js.map +0 -1
  81. package/ecs/database/type-investigation.test.d.ts +0 -1
  82. package/ecs/database/type-investigation.test.js +0 -54
  83. package/ecs/database/type-investigation.test.js.map +0 -1
  84. package/lit/decorators/apply-decorator.d.ts +0 -1
  85. package/lit/decorators/apply-decorator.js +0 -19
  86. package/lit/decorators/apply-decorator.js.map +0 -1
  87. package/lit/decorators/apply-service-decorators.d.ts +0 -1
  88. package/lit/decorators/apply-service-decorators.js +0 -13
  89. package/lit/decorators/apply-service-decorators.js.map +0 -1
  90. package/lit/decorators/index.d.ts +0 -3
  91. package/lit/decorators/index.js +0 -5
  92. package/lit/decorators/index.js.map +0 -1
  93. package/lit/decorators/require-service.d.ts +0 -1
  94. package/lit/decorators/require-service.js +0 -14
  95. package/lit/decorators/require-service.js.map +0 -1
  96. package/lit/elements/application-element.d.ts +0 -9
  97. package/lit/elements/application-element.js +0 -42
  98. package/lit/elements/application-element.js.map +0 -1
  99. package/lit/elements/application-host.d.ts +0 -16
  100. package/lit/elements/application-host.js +0 -39
  101. package/lit/elements/application-host.js.map +0 -1
  102. package/lit/elements/database-element.d.ts +0 -10
  103. package/lit/elements/database-element.js +0 -40
  104. package/lit/elements/database-element.js.map +0 -1
  105. package/lit/elements/index.d.ts +0 -3
  106. package/lit/elements/index.js +0 -5
  107. package/lit/elements/index.js.map +0 -1
  108. package/lit/functions/index.d.ts +0 -1
  109. package/lit/functions/index.js +0 -3
  110. package/lit/functions/index.js.map +0 -1
  111. package/lit/functions/iterate-self-and-ancestors.d.ts +0 -1
  112. package/lit/functions/iterate-self-and-ancestors.js +0 -24
  113. package/lit/functions/iterate-self-and-ancestors.js.map +0 -1
  114. package/lit/hooks/attach-decorator.d.ts +0 -4
  115. package/lit/hooks/attach-decorator.js +0 -26
  116. package/lit/hooks/attach-decorator.js.map +0 -1
  117. package/lit/hooks/component/component.d.ts +0 -10
  118. package/lit/hooks/component/component.js.map +0 -1
  119. package/lit/hooks/component/stack.d.ts +0 -6
  120. package/lit/hooks/component/stack.js +0 -16
  121. package/lit/hooks/component/stack.js.map +0 -1
  122. package/lit/hooks/index.d.ts +0 -19
  123. package/lit/hooks/index.js +0 -21
  124. package/lit/hooks/index.js.map +0 -1
  125. package/lit/hooks/use-connected.d.ts +0 -2
  126. package/lit/hooks/use-connected.js +0 -32
  127. package/lit/hooks/use-connected.js.map +0 -1
  128. package/lit/hooks/use-debounce.d.ts +0 -8
  129. package/lit/hooks/use-debounce.js +0 -21
  130. package/lit/hooks/use-debounce.js.map +0 -1
  131. package/lit/hooks/use-drag-observe.d.ts +0 -25
  132. package/lit/hooks/use-drag-observe.js +0 -35
  133. package/lit/hooks/use-drag-observe.js.map +0 -1
  134. package/lit/hooks/use-drag-transaction.d.ts +0 -7
  135. package/lit/hooks/use-drag-transaction.js +0 -35
  136. package/lit/hooks/use-drag-transaction.js.map +0 -1
  137. package/lit/hooks/use-draggable.d.ts +0 -15
  138. package/lit/hooks/use-draggable.js +0 -96
  139. package/lit/hooks/use-draggable.js.map +0 -1
  140. package/lit/hooks/use-effect.d.ts +0 -3
  141. package/lit/hooks/use-effect.js +0 -14
  142. package/lit/hooks/use-effect.js.map +0 -1
  143. package/lit/hooks/use-element.d.ts +0 -7
  144. package/lit/hooks/use-element.js +0 -67
  145. package/lit/hooks/use-element.js.map +0 -1
  146. package/lit/hooks/use-memo.d.ts +0 -1
  147. package/lit/hooks/use-memo.js +0 -13
  148. package/lit/hooks/use-memo.js.map +0 -1
  149. package/lit/hooks/use-observable-values.d.ts +0 -4
  150. package/lit/hooks/use-observable-values.js +0 -9
  151. package/lit/hooks/use-observable-values.js.map +0 -1
  152. package/lit/hooks/use-observable.d.ts +0 -2
  153. package/lit/hooks/use-observable.js +0 -13
  154. package/lit/hooks/use-observable.js.map +0 -1
  155. package/lit/hooks/use-ref.d.ts +0 -3
  156. package/lit/hooks/use-ref.js +0 -7
  157. package/lit/hooks/use-ref.js.map +0 -1
  158. package/lit/hooks/use-resize-observer.d.ts +0 -12
  159. package/lit/hooks/use-resize-observer.js +0 -23
  160. package/lit/hooks/use-resize-observer.js.map +0 -1
  161. package/lit/hooks/use-state.d.ts +0 -2
  162. package/lit/hooks/use-state.js +0 -15
  163. package/lit/hooks/use-state.js.map +0 -1
  164. package/lit/hooks/use-updated.d.ts +0 -4
  165. package/lit/hooks/use-updated.js +0 -40
  166. package/lit/hooks/use-updated.js.map +0 -1
  167. package/lit/hooks/use-window-event.d.ts +0 -1
  168. package/lit/hooks/use-window-event.js +0 -11
  169. package/lit/hooks/use-window-event.js.map +0 -1
  170. package/lit/hooks/with-hooks.d.ts +0 -2
  171. package/lit/hooks/with-hooks.js +0 -16
  172. package/lit/hooks/with-hooks.js.map +0 -1
  173. package/lit/index.d.ts +0 -4
  174. package/lit/index.js +0 -5
  175. package/lit/index.js.map +0 -1
  176. package/normalize.test.d.ts +0 -1
  177. package/normalize.test.js +0 -28
  178. package/normalize.test.js.map +0 -1
  179. package/samples/index.d.ts +0 -13
  180. package/samples/index.js +0 -7
  181. package/samples/index.js.map +0 -1
  182. package/samples/todo/elements/todo-list/todo-list-presentation.d.ts +0 -8
  183. package/samples/todo/elements/todo-list/todo-list-presentation.js +0 -12
  184. package/samples/todo/elements/todo-list/todo-list-presentation.js.map +0 -1
  185. package/samples/todo/elements/todo-list/todo-list.css.d.ts +0 -1
  186. package/samples/todo/elements/todo-list/todo-list.css.js +0 -11
  187. package/samples/todo/elements/todo-list/todo-list.css.js.map +0 -1
  188. package/samples/todo/elements/todo-list/todo-list.d.ts +0 -12
  189. package/samples/todo/elements/todo-list/todo-list.js +0 -44
  190. package/samples/todo/elements/todo-list/todo-list.js.map +0 -1
  191. package/samples/todo/elements/todo-row/index.d.ts +0 -1
  192. package/samples/todo/elements/todo-row/index.js +0 -3
  193. package/samples/todo/elements/todo-row/index.js.map +0 -1
  194. package/samples/todo/elements/todo-row/todo-row-presentation.d.ts +0 -18
  195. package/samples/todo/elements/todo-row/todo-row-presentation.js +0 -50
  196. package/samples/todo/elements/todo-row/todo-row-presentation.js.map +0 -1
  197. package/samples/todo/elements/todo-row/todo-row.css.d.ts +0 -1
  198. package/samples/todo/elements/todo-row/todo-row.css.js +0 -49
  199. package/samples/todo/elements/todo-row/todo-row.css.js.map +0 -1
  200. package/samples/todo/elements/todo-row/todo-row.d.ts +0 -14
  201. package/samples/todo/elements/todo-row/todo-row.js +0 -44
  202. package/samples/todo/elements/todo-row/todo-row.js.map +0 -1
  203. package/samples/todo/elements/todo-toolbar/index.d.ts +0 -1
  204. package/samples/todo/elements/todo-toolbar/index.js +0 -3
  205. package/samples/todo/elements/todo-toolbar/index.js.map +0 -1
  206. package/samples/todo/elements/todo-toolbar/todo-toolbar-presentation.d.ts +0 -22
  207. package/samples/todo/elements/todo-toolbar/todo-toolbar-presentation.js +0 -41
  208. package/samples/todo/elements/todo-toolbar/todo-toolbar-presentation.js.map +0 -1
  209. package/samples/todo/elements/todo-toolbar/todo-toolbar.css.d.ts +0 -1
  210. package/samples/todo/elements/todo-toolbar/todo-toolbar.css.js +0 -34
  211. package/samples/todo/elements/todo-toolbar/todo-toolbar.css.js.map +0 -1
  212. package/samples/todo/elements/todo-toolbar/todo-toolbar.d.ts +0 -11
  213. package/samples/todo/elements/todo-toolbar/todo-toolbar.js +0 -61
  214. package/samples/todo/elements/todo-toolbar/todo-toolbar.js.map +0 -1
  215. package/samples/todo/elements/todo-undo-redo/index.d.ts +0 -1
  216. package/samples/todo/elements/todo-undo-redo/index.js +0 -3
  217. package/samples/todo/elements/todo-undo-redo/index.js.map +0 -1
  218. package/samples/todo/elements/todo-undo-redo/todo-undo-redo-presentation.d.ts +0 -17
  219. package/samples/todo/elements/todo-undo-redo/todo-undo-redo-presentation.js +0 -29
  220. package/samples/todo/elements/todo-undo-redo/todo-undo-redo-presentation.js.map +0 -1
  221. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.css.d.ts +0 -1
  222. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.css.js +0 -12
  223. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.css.js.map +0 -1
  224. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.d.ts +0 -11
  225. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.js +0 -36
  226. package/samples/todo/elements/todo-undo-redo/todo-undo-redo.js.map +0 -1
  227. package/samples/todo/services/dependent-state-service/create-dependent-state-service.d.ts +0 -6
  228. package/samples/todo/services/dependent-state-service/create-dependent-state-service.js +0 -5
  229. package/samples/todo/services/dependent-state-service/create-dependent-state-service.js.map +0 -1
  230. package/samples/todo/services/dependent-state-service/dependent-state/all-todos.d.ts +0 -2
  231. package/samples/todo/services/dependent-state-service/dependent-state/all-todos.js +0 -2
  232. package/samples/todo/services/dependent-state-service/dependent-state/all-todos.js.map +0 -1
  233. package/samples/todo/services/dependent-state-service/dependent-state/complete-todos.d.ts +0 -2
  234. package/samples/todo/services/dependent-state-service/dependent-state/complete-todos.js +0 -2
  235. package/samples/todo/services/dependent-state-service/dependent-state/complete-todos.js.map +0 -1
  236. package/samples/todo/services/dependent-state-service/dependent-state/incomplete-todos.d.ts +0 -2
  237. package/samples/todo/services/dependent-state-service/dependent-state/incomplete-todos.js +0 -2
  238. package/samples/todo/services/dependent-state-service/dependent-state/incomplete-todos.js.map +0 -1
  239. package/samples/todo/services/dependent-state-service/dependent-state/index.d.ts +0 -3
  240. package/samples/todo/services/dependent-state-service/dependent-state/index.js +0 -5
  241. package/samples/todo/services/dependent-state-service/dependent-state/index.js.map +0 -1
  242. package/samples/todo/services/dependent-state-service/dependent-state-service.d.ts +0 -2
  243. package/samples/todo/services/dependent-state-service/dependent-state-service.js +0 -2
  244. package/samples/todo/services/dependent-state-service/dependent-state-service.js.map +0 -1
  245. package/samples/todo/services/main-service/create-main-service.d.ts +0 -8
  246. package/samples/todo/services/main-service/create-main-service.js +0 -39
  247. package/samples/todo/services/main-service/create-main-service.js.map +0 -1
  248. package/samples/todo/services/main-service/todo-main-service.d.ts +0 -18
  249. package/samples/todo/services/main-service/todo-main-service.js +0 -2
  250. package/samples/todo/services/main-service/todo-main-service.js.map +0 -1
  251. package/samples/todo/services/state-service/create-todo-database.d.ts +0 -37
  252. package/samples/todo/services/state-service/create-todo-database.js +0 -10
  253. package/samples/todo/services/state-service/create-todo-database.js.map +0 -1
  254. package/samples/todo/services/state-service/create-todo-store.d.ts +0 -37
  255. package/samples/todo/services/state-service/create-todo-store.js +0 -24
  256. package/samples/todo/services/state-service/create-todo-store.js.map +0 -1
  257. package/samples/todo/services/state-service/todo-state-service.d.ts +0 -5
  258. package/samples/todo/services/state-service/todo-state-service.js +0 -2
  259. package/samples/todo/services/state-service/todo-state-service.js.map +0 -1
  260. package/samples/todo/services/state-service/transactions/create-bulk-todos.d.ts +0 -2
  261. package/samples/todo/services/state-service/transactions/create-bulk-todos.js +0 -10
  262. package/samples/todo/services/state-service/transactions/create-bulk-todos.js.map +0 -1
  263. package/samples/todo/services/state-service/transactions/create-todo.d.ts +0 -5
  264. package/samples/todo/services/state-service/transactions/create-todo.js +0 -13
  265. package/samples/todo/services/state-service/transactions/create-todo.js.map +0 -1
  266. package/samples/todo/services/state-service/transactions/create-todo.test.d.ts +0 -1
  267. package/samples/todo/services/state-service/transactions/create-todo.test.js +0 -16
  268. package/samples/todo/services/state-service/transactions/create-todo.test.js.map +0 -1
  269. package/samples/todo/services/state-service/transactions/delete-all-todos.d.ts +0 -2
  270. package/samples/todo/services/state-service/transactions/delete-all-todos.js +0 -16
  271. package/samples/todo/services/state-service/transactions/delete-all-todos.js.map +0 -1
  272. package/samples/todo/services/state-service/transactions/delete-todo.d.ts +0 -3
  273. package/samples/todo/services/state-service/transactions/delete-todo.js +0 -8
  274. package/samples/todo/services/state-service/transactions/delete-todo.js.map +0 -1
  275. package/samples/todo/services/state-service/transactions/delete-todo.test.d.ts +0 -1
  276. package/samples/todo/services/state-service/transactions/delete-todo.test.js +0 -24
  277. package/samples/todo/services/state-service/transactions/delete-todo.test.js.map +0 -1
  278. package/samples/todo/services/state-service/transactions/drag-todo.d.ts +0 -7
  279. package/samples/todo/services/state-service/transactions/drag-todo.js +0 -17
  280. package/samples/todo/services/state-service/transactions/drag-todo.js.map +0 -1
  281. package/samples/todo/services/state-service/transactions/index.d.ts +0 -6
  282. package/samples/todo/services/state-service/transactions/index.js +0 -9
  283. package/samples/todo/services/state-service/transactions/index.js.map +0 -1
  284. package/samples/todo/services/state-service/transactions/reorder-todos.d.ts +0 -6
  285. package/samples/todo/services/state-service/transactions/reorder-todos.js +0 -11
  286. package/samples/todo/services/state-service/transactions/reorder-todos.js.map +0 -1
  287. package/samples/todo/services/state-service/transactions/toggle-complete.d.ts +0 -3
  288. package/samples/todo/services/state-service/transactions/toggle-complete.js +0 -11
  289. package/samples/todo/services/state-service/transactions/toggle-complete.js.map +0 -1
  290. package/samples/todo/services/state-service/transactions/toggle-complete.test.d.ts +0 -1
  291. package/samples/todo/services/state-service/transactions/toggle-complete.test.js +0 -65
  292. package/samples/todo/services/state-service/transactions/toggle-complete.test.js.map +0 -1
  293. package/samples/todo/todo-element.d.ts +0 -4
  294. package/samples/todo/todo-element.js +0 -4
  295. package/samples/todo/todo-element.js.map +0 -1
  296. package/samples/todo/todo-host.d.ts +0 -8
  297. package/samples/todo/todo-host.js +0 -35
  298. package/samples/todo/todo-host.js.map +0 -1
  299. package/samples/todo/todo-main-element.d.ts +0 -10
  300. package/samples/todo/todo-main-element.js +0 -47
  301. package/samples/todo/todo-main-element.js.map +0 -1
  302. package/samples/todo/todo-sample.d.ts +0 -3
  303. package/samples/todo/todo-sample.js +0 -19
  304. package/samples/todo/todo-sample.js.map +0 -1
  305. package/service/is-data-service.js +0 -2
  306. package/service/is-data-service.js.map +0 -1
  307. package/typed-buffer/public.d.ts +0 -2
  308. package/typed-buffer/public.js +0 -4
  309. package/typed-buffer/public.js.map +0 -1
  310. /package/{ecs/database/create-plugin-type.type-test.d.ts → service/async-data-service/create-lazy.test.d.ts} +0 -0
@@ -0,0 +1,194 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ // ============================================================================
3
+ // MAIN FUNCTION SIGNATURE
4
+ // ============================================================================
5
+ /**
6
+ * Creates a lazy-loading wrapper factory for an AsyncDataService.
7
+ * The real service is only loaded when the first property is accessed.
8
+ * All calls are queued and executed in order once the service loads.
9
+ *
10
+ * @param load - Function that loads and returns the real service (may accept args)
11
+ * @param properties - Object describing how to wrap each service property
12
+ * @returns A factory function that creates lazy service instances
13
+ *
14
+ * TypeScript will enforce:
15
+ * - All service properties must be declared in properties object
16
+ * - Each descriptor must match the actual property type
17
+ * - Clear errors indicate what is missing or wrong
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Service with no args
22
+ * const createLazySimple = createLazy(
23
+ * () => import('./simple').then(m => m.create()),
24
+ * { data: 'observe', fetch: 'fn:promise' }
25
+ * );
26
+ * const service = createLazySimple();
27
+ *
28
+ * // Service with args
29
+ * const createLazyConfig = createLazy(
30
+ * (config: Config) => import('./service').then(m => m.create(config)),
31
+ * { data: 'observe', fetch: 'fn:promise' }
32
+ * );
33
+ * const service = createLazyConfig({ apiUrl: '...' });
34
+ * ```
35
+ */
36
+ export function createLazy(load, properties) {
37
+ // Return factory function that creates lazy service instances
38
+ return ((...factoryArgs) => {
39
+ // Shared loading state for this instance
40
+ let loadPromise = null;
41
+ let loadedService = null;
42
+ const ensureLoading = () => {
43
+ if (loadedService) {
44
+ return Promise.resolve(loadedService);
45
+ }
46
+ if (loadPromise) {
47
+ return loadPromise;
48
+ }
49
+ loadPromise = load(...factoryArgs).then((service) => {
50
+ loadedService = service;
51
+ return service;
52
+ });
53
+ return loadPromise;
54
+ };
55
+ // Build lazy service object
56
+ const lazyService = {
57
+ serviceName: 'lazy-service',
58
+ };
59
+ // Wrap each property based on its descriptor
60
+ for (const [key, descriptor] of Object.entries(properties)) {
61
+ if (descriptor === 'observe') {
62
+ // Observe property - defer subscription until service loads
63
+ lazyService[key] = (notify) => {
64
+ let unobserveReal = null;
65
+ let isCancelled = false;
66
+ ensureLoading().then((service) => {
67
+ if (!isCancelled && service.serviceName !== 'lazy-service') {
68
+ // Update lazy service name once real service loads
69
+ lazyService.serviceName = `lazy-${service.serviceName}`;
70
+ }
71
+ if (!isCancelled) {
72
+ unobserveReal = service[key](notify);
73
+ }
74
+ });
75
+ return () => {
76
+ isCancelled = true;
77
+ unobserveReal?.();
78
+ };
79
+ };
80
+ }
81
+ else if (descriptor === 'fn:promise') {
82
+ const queue = [];
83
+ let isProcessing = false;
84
+ lazyService[key] = (...args) => {
85
+ return new Promise((resolve, reject) => {
86
+ queue.push({ args, resolve, reject });
87
+ if (!isProcessing) {
88
+ isProcessing = true;
89
+ ensureLoading().then(async (service) => {
90
+ if (service.serviceName !== 'lazy-service') {
91
+ lazyService.serviceName = `lazy-${service.serviceName}`;
92
+ }
93
+ // Execute all queued calls in order
94
+ while (queue.length > 0) {
95
+ const call = queue.shift();
96
+ try {
97
+ const result = await service[key](...call.args);
98
+ call.resolve(result);
99
+ }
100
+ catch (error) {
101
+ call.reject(error);
102
+ }
103
+ }
104
+ }).catch(error => {
105
+ // Service load failed, reject all queued calls
106
+ while (queue.length > 0) {
107
+ queue.shift().reject(error);
108
+ }
109
+ });
110
+ }
111
+ });
112
+ };
113
+ }
114
+ else if (descriptor === 'fn:void') {
115
+ // Void function - queue calls and execute after load
116
+ const queue = [];
117
+ let isProcessing = false;
118
+ lazyService[key] = (...args) => {
119
+ queue.push(args);
120
+ if (!isProcessing) {
121
+ isProcessing = true;
122
+ ensureLoading().then((service) => {
123
+ if (service.serviceName !== 'lazy-service') {
124
+ lazyService.serviceName = `lazy-${service.serviceName}`;
125
+ }
126
+ // Execute all queued calls in order
127
+ while (queue.length > 0) {
128
+ const args = queue.shift();
129
+ service[key](...args);
130
+ }
131
+ });
132
+ }
133
+ };
134
+ }
135
+ else if (descriptor === 'fn:observe') {
136
+ // Observe function - returns Observe that waits for service
137
+ lazyService[key] = (...args) => {
138
+ return (notify) => {
139
+ let unobserveReal = null;
140
+ let isCancelled = false;
141
+ ensureLoading().then((service) => {
142
+ if (service.serviceName !== 'lazy-service') {
143
+ lazyService.serviceName = `lazy-${service.serviceName}`;
144
+ }
145
+ if (!isCancelled) {
146
+ const realObserve = service[key](...args);
147
+ unobserveReal = realObserve(notify);
148
+ }
149
+ });
150
+ return () => {
151
+ isCancelled = true;
152
+ unobserveReal?.();
153
+ };
154
+ };
155
+ };
156
+ }
157
+ else if (descriptor === 'fn:generator') {
158
+ // AsyncGenerator function - returns generator that waits for service
159
+ lazyService[key] = (...args) => {
160
+ let realGenerator = null;
161
+ return {
162
+ async next() {
163
+ if (!realGenerator) {
164
+ const service = await ensureLoading();
165
+ if (service.serviceName !== 'lazy-service') {
166
+ lazyService.serviceName = `lazy-${service.serviceName}`;
167
+ }
168
+ realGenerator = service[key](...args);
169
+ }
170
+ return realGenerator.next();
171
+ },
172
+ async return(value) {
173
+ if (realGenerator) {
174
+ return realGenerator.return(value);
175
+ }
176
+ return { done: true, value: value };
177
+ },
178
+ async throw(e) {
179
+ if (realGenerator) {
180
+ return realGenerator.throw(e);
181
+ }
182
+ throw e;
183
+ },
184
+ [Symbol.asyncIterator]() {
185
+ return this;
186
+ }
187
+ };
188
+ };
189
+ }
190
+ }
191
+ return lazyService;
192
+ });
193
+ }
194
+ //# sourceMappingURL=create-lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-lazy.js","sourceRoot":"","sources":["../../../src/service/async-data-service/create-lazy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,477 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { describe, test } from 'vitest';
3
+ import { assert } from 'riteway/vitest';
4
+ import { createLazy } from "./create-lazy.js";
5
+ // ============================================================================
6
+ // VALID USAGE TESTS
7
+ // ============================================================================
8
+ // ✅ Test 1: Complete descriptor for SimpleAuthService
9
+ const validAuth = createLazy(() => Promise.resolve({}), {
10
+ isSignedIn: 'observe',
11
+ accessToken: 'observe',
12
+ userProfile: 'observe',
13
+ showSignInDialog: 'fn:void',
14
+ hideSignInDialog: 'fn:void',
15
+ refreshToken: 'fn:promise',
16
+ signIn: 'fn:promise',
17
+ signOut: 'fn:promise'
18
+ });
19
+ // ✅ Test 2: Service with function returning Observe
20
+ const validObserveFn = createLazy(() => Promise.resolve({}), {
21
+ allUsers: 'observe',
22
+ selectUser: 'fn:observe',
23
+ fetchData: 'fn:promise'
24
+ });
25
+ // ✅ Test 3: Service with AsyncGenerator
26
+ const validGenerator = createLazy(() => Promise.resolve({}), {
27
+ status: 'observe',
28
+ streamEvents: 'fn:generator',
29
+ cancel: 'fn:void'
30
+ });
31
+ const validWithArgs = createLazy((args) => {
32
+ // args is properly typed as ServiceConfig
33
+ console.log(args.apiUrl);
34
+ return Promise.resolve({});
35
+ }, {
36
+ config: 'observe',
37
+ fetch: 'fn:promise'
38
+ });
39
+ // ============================================================================
40
+ // ERROR TESTS (These should produce TypeScript errors)
41
+ // ============================================================================
42
+ // ❌ Test 5: Missing property 'refreshToken'
43
+ const errorMissing = createLazy(() => Promise.resolve({}),
44
+ // @ts-expect-error - Missing property 'refreshToken' in descriptor
45
+ {
46
+ isSignedIn: 'observe',
47
+ accessToken: 'observe',
48
+ userProfile: 'observe',
49
+ showSignInDialog: 'fn:void',
50
+ hideSignInDialog: 'fn:void',
51
+ // Missing: refreshToken
52
+ signIn: 'fn:promise',
53
+ signOut: 'fn:promise'
54
+ });
55
+ // ❌ Test 6: Wrong descriptor type (observe property marked as fn:observe)
56
+ const errorWrongType1 = createLazy(() => Promise.resolve({}), {
57
+ // @ts-expect-error - Wrong descriptor type
58
+ isSignedIn: 'fn:observe', // WRONG: should be 'observe'
59
+ accessToken: 'observe',
60
+ userProfile: 'observe',
61
+ showSignInDialog: 'fn:void',
62
+ hideSignInDialog: 'fn:void',
63
+ refreshToken: 'fn:promise',
64
+ signIn: 'fn:promise',
65
+ signOut: 'fn:promise'
66
+ });
67
+ // ❌ Test 7: Wrong descriptor type (void function marked as fn:promise)
68
+ const errorWrongType2 = createLazy(() => Promise.resolve({}), {
69
+ isSignedIn: 'observe',
70
+ accessToken: 'observe',
71
+ userProfile: 'observe',
72
+ // @ts-expect-error - Wrong descriptor type
73
+ showSignInDialog: 'fn:promise', // WRONG: should be 'fn:void'
74
+ hideSignInDialog: 'fn:void',
75
+ refreshToken: 'fn:promise',
76
+ signIn: 'fn:promise',
77
+ signOut: 'fn:promise'
78
+ });
79
+ // ❌ Test 8: Extra property that doesn't exist in service
80
+ const errorExtra = createLazy(() => Promise.resolve({}), {
81
+ allUsers: 'observe',
82
+ selectUser: 'fn:observe',
83
+ fetchData: 'fn:promise',
84
+ // @ts-expect-error - Extra property
85
+ unknownProperty: 'observe' // EXTRA: doesn't exist in service
86
+ });
87
+ // ❌ Test 9: Wrong descriptor for fn:observe (marked as observe)
88
+ const errorObserveFn = createLazy(() => Promise.resolve({}), {
89
+ allUsers: 'observe',
90
+ // @ts-expect-error - Wrong descriptor type
91
+ selectUser: 'observe', // WRONG: should be 'fn:observe'
92
+ fetchData: 'fn:promise'
93
+ });
94
+ // ❌ Test 10: Wrong descriptor for generator
95
+ const errorGenerator = createLazy(() => Promise.resolve({}), {
96
+ status: 'observe',
97
+ // @ts-expect-error - Wrong descriptor type
98
+ streamEvents: 'fn:promise', // WRONG: should be 'fn:generator'
99
+ cancel: 'fn:void'
100
+ });
101
+ // ============================================================================
102
+ // RUNTIME TESTS
103
+ // ============================================================================
104
+ describe('createLazy', () => {
105
+ test('factory pattern', async () => {
106
+ const createTestService = () => {
107
+ return Promise.resolve({
108
+ serviceName: 'test-service',
109
+ value: (notify) => {
110
+ notify('test-value');
111
+ return () => { };
112
+ }
113
+ });
114
+ };
115
+ const factory = createLazy(createTestService, { value: 'observe' });
116
+ assert({
117
+ given: 'createLazy is called',
118
+ should: 'return a factory function',
119
+ actual: typeof factory,
120
+ expected: 'function'
121
+ });
122
+ const service = factory();
123
+ assert({
124
+ given: 'factory function is called',
125
+ should: 'return a service with serviceName',
126
+ actual: typeof service.serviceName,
127
+ expected: 'string'
128
+ });
129
+ });
130
+ test('observe property', async () => {
131
+ const createTestService = () => {
132
+ return Promise.resolve({
133
+ serviceName: 'test-service',
134
+ value: (notify) => {
135
+ notify('test-value');
136
+ return () => { };
137
+ }
138
+ });
139
+ };
140
+ const factory = createLazy(createTestService, { value: 'observe' });
141
+ const service = factory();
142
+ let receivedValue = null;
143
+ const unobserve = service.value((value) => {
144
+ receivedValue = value;
145
+ });
146
+ // Wait for async load
147
+ await new Promise(resolve => setTimeout(resolve, 10));
148
+ assert({
149
+ given: 'observe property is subscribed',
150
+ should: 'receive value from real service after load',
151
+ actual: receivedValue,
152
+ expected: 'test-value'
153
+ });
154
+ unobserve();
155
+ });
156
+ test('observe property returns same instance', async () => {
157
+ const createTestService = () => {
158
+ return Promise.resolve({
159
+ serviceName: 'test-service',
160
+ value: (notify) => {
161
+ notify('test-value');
162
+ return () => { };
163
+ }
164
+ });
165
+ };
166
+ const factory = createLazy(createTestService, { value: 'observe' });
167
+ const service = factory();
168
+ const observe1 = service.value;
169
+ const observe2 = service.value;
170
+ assert({
171
+ given: 'observe property is accessed multiple times',
172
+ should: 'return the same Observe instance',
173
+ actual: observe1 === observe2,
174
+ expected: true
175
+ });
176
+ });
177
+ test('promise function', async () => {
178
+ const createTestService = () => {
179
+ return Promise.resolve({
180
+ serviceName: 'test-service',
181
+ fetchData: async (id) => {
182
+ return { value: `data-${id}` };
183
+ }
184
+ });
185
+ };
186
+ const factory = createLazy(createTestService, { fetchData: 'fn:promise' });
187
+ const service = factory();
188
+ const result = await service.fetchData('123');
189
+ assert({
190
+ given: 'promise function is called',
191
+ should: 'return result from real service',
192
+ actual: result.value,
193
+ expected: 'data-123'
194
+ });
195
+ });
196
+ test('promise function queuing', async () => {
197
+ const calls = [];
198
+ const createTestService = () => {
199
+ return new Promise(resolve => {
200
+ setTimeout(() => {
201
+ resolve({
202
+ serviceName: 'test-service',
203
+ fetchData: async (id) => {
204
+ calls.push(id);
205
+ return `result-${id}`;
206
+ }
207
+ });
208
+ }, 50);
209
+ });
210
+ };
211
+ const factory = createLazy(createTestService, { fetchData: 'fn:promise' });
212
+ const service = factory();
213
+ // Call multiple times before service loads
214
+ const p1 = service.fetchData('a');
215
+ const p2 = service.fetchData('b');
216
+ const p3 = service.fetchData('c');
217
+ const results = await Promise.all([p1, p2, p3]);
218
+ assert({
219
+ given: 'multiple calls made before service loads',
220
+ should: 'execute all calls in order',
221
+ actual: calls.join(','),
222
+ expected: 'a,b,c'
223
+ });
224
+ assert({
225
+ given: 'queued calls complete',
226
+ should: 'return correct results',
227
+ actual: results.join(','),
228
+ expected: 'result-a,result-b,result-c'
229
+ });
230
+ });
231
+ test('promise function returns same instance', async () => {
232
+ const factory = createLazy(() => Promise.resolve({
233
+ serviceName: 'test-service',
234
+ fetchData: async (id) => `result-${id}`
235
+ }), { fetchData: 'fn:promise' });
236
+ const service = factory();
237
+ const fn1 = service.fetchData;
238
+ const fn2 = service.fetchData;
239
+ assert({
240
+ given: 'promise function property is accessed multiple times',
241
+ should: 'return the same function instance',
242
+ actual: fn1 === fn2,
243
+ expected: true
244
+ });
245
+ });
246
+ test('promise function calls return different promises', async () => {
247
+ const factory = createLazy(() => Promise.resolve({
248
+ serviceName: 'test-service',
249
+ fetchData: async (id) => `result-${id}`
250
+ }), { fetchData: 'fn:promise' });
251
+ const service = factory();
252
+ const promise1 = service.fetchData('id-1');
253
+ const promise2 = service.fetchData('id-1');
254
+ const promise3 = service.fetchData('id-2');
255
+ assert({
256
+ given: 'promise function is called multiple times',
257
+ should: 'return different Promise instances',
258
+ actual: promise1 !== promise2 && promise1 !== promise3,
259
+ expected: true
260
+ });
261
+ const results = await Promise.all([promise1, promise2, promise3]);
262
+ assert({
263
+ given: 'promise function called with different args',
264
+ should: 'resolve to correct values independently',
265
+ actual: results.join(','),
266
+ expected: 'result-id-1,result-id-1,result-id-2'
267
+ });
268
+ });
269
+ test('void function', async () => {
270
+ const events = [];
271
+ const createTestService = () => {
272
+ return Promise.resolve({
273
+ serviceName: 'test-service',
274
+ track: (event) => {
275
+ events.push(event);
276
+ }
277
+ });
278
+ };
279
+ const factory = createLazy(createTestService, { track: 'fn:void' });
280
+ const service = factory();
281
+ service.track('event-1');
282
+ service.track('event-2');
283
+ // Wait for async load and execution
284
+ await new Promise(resolve => setTimeout(resolve, 10));
285
+ assert({
286
+ given: 'void functions are called',
287
+ should: 'execute all calls in order after load',
288
+ actual: events.join(','),
289
+ expected: 'event-1,event-2'
290
+ });
291
+ });
292
+ test('observe function', async () => {
293
+ const createTestService = () => {
294
+ return Promise.resolve({
295
+ serviceName: 'test-service',
296
+ selectUser: (id) => (notify) => {
297
+ notify(`user-${id}`);
298
+ return () => { };
299
+ }
300
+ });
301
+ };
302
+ const factory = createLazy(createTestService, { selectUser: 'fn:observe' });
303
+ const service = factory();
304
+ let receivedValue = null;
305
+ const observe = service.selectUser('123');
306
+ const unobserve = observe((value) => {
307
+ receivedValue = value;
308
+ });
309
+ // Wait for async load
310
+ await new Promise(resolve => setTimeout(resolve, 10));
311
+ assert({
312
+ given: 'observe function is called and subscribed',
313
+ should: 'receive value from real service',
314
+ actual: receivedValue,
315
+ expected: 'user-123'
316
+ });
317
+ unobserve();
318
+ });
319
+ test('observe function returns same instance', async () => {
320
+ const factory = createLazy(() => Promise.resolve({
321
+ serviceName: 'test-service',
322
+ selectUser: (id) => (notify) => {
323
+ notify(`user-${id}`);
324
+ return () => { };
325
+ }
326
+ }), { selectUser: 'fn:observe' });
327
+ const service = factory();
328
+ const fn1 = service.selectUser;
329
+ const fn2 = service.selectUser;
330
+ assert({
331
+ given: 'observe function property is accessed multiple times',
332
+ should: 'return the same function instance',
333
+ actual: fn1 === fn2,
334
+ expected: true
335
+ });
336
+ });
337
+ test('observe function calls return different instances', async () => {
338
+ const factory = createLazy(() => Promise.resolve({
339
+ serviceName: 'test-service',
340
+ selectUser: (id) => (notify) => {
341
+ notify(`user-${id}`);
342
+ return () => { };
343
+ }
344
+ }), { selectUser: 'fn:observe' });
345
+ const service = factory();
346
+ const observe1 = service.selectUser('id-1');
347
+ const observe2 = service.selectUser('id-1');
348
+ const observe3 = service.selectUser('id-2');
349
+ assert({
350
+ given: 'observe function is called multiple times with same args',
351
+ should: 'return different Observe instances',
352
+ actual: observe1 !== observe2,
353
+ expected: true
354
+ });
355
+ assert({
356
+ given: 'observe function is called with different args',
357
+ should: 'return different Observe instances',
358
+ actual: observe1 !== observe3,
359
+ expected: true
360
+ });
361
+ });
362
+ test('observe function calls with different args work independently', async () => {
363
+ const factory = createLazy(() => Promise.resolve({
364
+ serviceName: 'test-service',
365
+ selectUser: (id) => (notify) => {
366
+ notify(`user-${id}`);
367
+ return () => { };
368
+ }
369
+ }), { selectUser: 'fn:observe' });
370
+ const service = factory();
371
+ const values = [];
372
+ const observe1 = service.selectUser('id-1');
373
+ const unobserve1 = observe1((value) => values.push(`obs1:${value}`));
374
+ const observe2 = service.selectUser('id-2');
375
+ const unobserve2 = observe2((value) => values.push(`obs2:${value}`));
376
+ // Wait for async load
377
+ await new Promise(resolve => setTimeout(resolve, 10));
378
+ assert({
379
+ given: 'multiple observe function calls with different args',
380
+ should: 'each receive their own values independently',
381
+ actual: values.sort().join(','),
382
+ expected: 'obs1:user-id-1,obs2:user-id-2'
383
+ });
384
+ unobserve1();
385
+ unobserve2();
386
+ });
387
+ test('generator function', async () => {
388
+ const createTestService = () => {
389
+ return Promise.resolve({
390
+ serviceName: 'test-service',
391
+ streamData: async function* () {
392
+ yield 1;
393
+ yield 2;
394
+ yield 3;
395
+ }
396
+ });
397
+ };
398
+ const factory = createLazy(createTestService, { streamData: 'fn:generator' });
399
+ const service = factory();
400
+ const values = [];
401
+ for await (const value of service.streamData()) {
402
+ values.push(value);
403
+ }
404
+ assert({
405
+ given: 'generator function is called',
406
+ should: 'yield all values from real service',
407
+ actual: values.join(','),
408
+ expected: '1,2,3'
409
+ });
410
+ });
411
+ test('generator function returns same instance', async () => {
412
+ const factory = createLazy(() => Promise.resolve({
413
+ serviceName: 'test-service',
414
+ streamData: async function* () {
415
+ yield 1;
416
+ yield 2;
417
+ }
418
+ }), { streamData: 'fn:generator' });
419
+ const service = factory();
420
+ const fn1 = service.streamData;
421
+ const fn2 = service.streamData;
422
+ assert({
423
+ given: 'generator function property is accessed multiple times',
424
+ should: 'return the same function instance',
425
+ actual: fn1 === fn2,
426
+ expected: true
427
+ });
428
+ });
429
+ test('generator function calls return different generators', async () => {
430
+ const factory = createLazy(() => Promise.resolve({
431
+ serviceName: 'test-service',
432
+ streamData: async function* (prefix) {
433
+ yield `${prefix}-1`;
434
+ yield `${prefix}-2`;
435
+ }
436
+ }), { streamData: 'fn:generator' });
437
+ const service = factory();
438
+ const gen1 = service.streamData('A');
439
+ const gen2 = service.streamData('B');
440
+ assert({
441
+ given: 'generator function is called multiple times',
442
+ should: 'return different AsyncGenerator instances',
443
+ actual: gen1 !== gen2,
444
+ expected: true
445
+ });
446
+ const values1 = [];
447
+ const values2 = [];
448
+ for await (const value of gen1) {
449
+ values1.push(value);
450
+ }
451
+ for await (const value of gen2) {
452
+ values2.push(value);
453
+ }
454
+ assert({
455
+ given: 'different generator instances with different args',
456
+ should: 'produce independent sequences',
457
+ actual: `${values1.join(',')}|${values2.join(',')}`,
458
+ expected: 'A-1,A-2|B-1,B-2'
459
+ });
460
+ });
461
+ test('void function returns same instance', async () => {
462
+ const factory = createLazy(() => Promise.resolve({
463
+ serviceName: 'test-service',
464
+ track: (event) => { }
465
+ }), { track: 'fn:void' });
466
+ const service = factory();
467
+ const fn1 = service.track;
468
+ const fn2 = service.track;
469
+ assert({
470
+ given: 'void function property is accessed multiple times',
471
+ should: 'return the same function instance',
472
+ actual: fn1 === fn2,
473
+ expected: true
474
+ });
475
+ });
476
+ });
477
+ //# sourceMappingURL=create-lazy.test.js.map