target-supabase-sdk 0.1.9 → 0.2.1

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 (464) hide show
  1. package/README.md +184 -1
  2. package/dist/browser.d.ts +60 -0
  3. package/dist/browser.d.ts.map +1 -0
  4. package/dist/browser.js +6 -0
  5. package/dist/browser.js.map +1 -0
  6. package/dist/chunks/create-logger-DyH3mZ8p.js +1028 -0
  7. package/dist/chunks/create-logger-DyH3mZ8p.js.map +1 -0
  8. package/dist/chunks/enable-log-persist-C_bSw6Kx.js +1362 -0
  9. package/dist/chunks/enable-log-persist-C_bSw6Kx.js.map +1 -0
  10. package/dist/chunks/word.interface-DLgRobKV.js +1973 -0
  11. package/dist/chunks/word.interface-DLgRobKV.js.map +1 -0
  12. package/dist/command/command.api.d.ts +1 -1
  13. package/dist/command/command.api.d.ts.map +1 -1
  14. package/dist/command/command.interface.d.ts +1 -1
  15. package/dist/command/command.interface.d.ts.map +1 -1
  16. package/dist/core.api.d.ts +10 -6
  17. package/dist/core.api.d.ts.map +1 -1
  18. package/dist/core.interface.d.ts +3 -2
  19. package/dist/core.interface.d.ts.map +1 -1
  20. package/dist/core.utils.d.ts +1 -1
  21. package/dist/core.utils.d.ts.map +1 -1
  22. package/dist/idea/idea.interface.d.ts +1 -1
  23. package/dist/idea/idea.interface.d.ts.map +1 -1
  24. package/dist/index.d.ts +2 -48
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/link/link.api.d.ts +1 -1
  27. package/dist/link/link.api.d.ts.map +1 -1
  28. package/dist/link/link.interface.d.ts +3 -3
  29. package/dist/link/link.interface.d.ts.map +1 -1
  30. package/dist/list/list.api.d.ts +3 -1
  31. package/dist/list/list.api.d.ts.map +1 -1
  32. package/dist/list/list.interface.d.ts +2 -2
  33. package/dist/list/list.interface.d.ts.map +1 -1
  34. package/dist/node/env/env-parsers.d.ts +19 -0
  35. package/dist/node/env/env-parsers.d.ts.map +1 -0
  36. package/dist/node/env/index.d.ts +11 -0
  37. package/dist/node/env/index.d.ts.map +1 -0
  38. package/dist/node/env/init-supabase-from-env.d.ts +17 -0
  39. package/dist/node/env/init-supabase-from-env.d.ts.map +1 -0
  40. package/dist/node/env/load-env.d.ts +20 -0
  41. package/dist/node/env/load-env.d.ts.map +1 -0
  42. package/dist/node/env/project-root.d.ts +11 -0
  43. package/dist/node/env/project-root.d.ts.map +1 -0
  44. package/dist/node/env/public-base-url.d.ts +10 -0
  45. package/dist/node/env/public-base-url.d.ts.map +1 -0
  46. package/dist/node/env/require-env.d.ts +3 -0
  47. package/dist/node/env/require-env.d.ts.map +1 -0
  48. package/dist/node/fs/json-state-store.d.ts +19 -0
  49. package/dist/node/fs/json-state-store.d.ts.map +1 -0
  50. package/dist/node/fs/read-source-file.d.ts +19 -0
  51. package/dist/node/fs/read-source-file.d.ts.map +1 -0
  52. package/dist/node/node-liveness.d.ts +30 -0
  53. package/dist/node/node-liveness.d.ts.map +1 -0
  54. package/dist/node/node-runtime.base.d.ts +60 -0
  55. package/dist/node/node-runtime.base.d.ts.map +1 -0
  56. package/dist/node/node.api.d.ts +4 -4
  57. package/dist/node/node.api.d.ts.map +1 -1
  58. package/dist/node/node.interface.d.ts +1 -6
  59. package/dist/node/node.interface.d.ts.map +1 -1
  60. package/dist/node/preload/run-service-preload.d.ts +14 -0
  61. package/dist/node/preload/run-service-preload.d.ts.map +1 -0
  62. package/dist/node/preload/service-preload.interface.d.ts +15 -0
  63. package/dist/node/preload/service-preload.interface.d.ts.map +1 -0
  64. package/dist/node/process/index.d.ts +5 -0
  65. package/dist/node/process/index.d.ts.map +1 -0
  66. package/dist/node/process/managed-child-processes.d.ts +37 -0
  67. package/dist/node/process/managed-child-processes.d.ts.map +1 -0
  68. package/dist/node/process/process-spawn.d.ts +27 -0
  69. package/dist/node/process/process-spawn.d.ts.map +1 -0
  70. package/dist/node/readiness/index.d.ts +9 -0
  71. package/dist/node/readiness/index.d.ts.map +1 -0
  72. package/dist/node/readiness/poll-until.d.ts +11 -0
  73. package/dist/node/readiness/poll-until.d.ts.map +1 -0
  74. package/dist/node/readiness/readiness-checks.d.ts +22 -0
  75. package/dist/node/readiness/readiness-checks.d.ts.map +1 -0
  76. package/dist/node/readiness/readiness.types.d.ts +12 -0
  77. package/dist/node/readiness/readiness.types.d.ts.map +1 -0
  78. package/dist/node/readiness/run-readiness-checks.d.ts +4 -0
  79. package/dist/node/readiness/run-readiness-checks.d.ts.map +1 -0
  80. package/dist/node/readiness/service-ready-gate.d.ts +26 -0
  81. package/dist/node/readiness/service-ready-gate.d.ts.map +1 -0
  82. package/dist/node.d.ts +36 -0
  83. package/dist/node.d.ts.map +1 -0
  84. package/dist/node.js +2483 -0
  85. package/dist/node.js.map +1 -0
  86. package/dist/parcel/chunk-fetch-registry.d.ts +14 -0
  87. package/dist/parcel/chunk-fetch-registry.d.ts.map +1 -0
  88. package/dist/parcel/chunk-url.utils.d.ts +9 -0
  89. package/dist/parcel/chunk-url.utils.d.ts.map +1 -0
  90. package/dist/parcel/parcel-manager.d.ts +44 -20
  91. package/dist/parcel/parcel-manager.d.ts.map +1 -1
  92. package/dist/parcel/parcel.api.d.ts +306 -0
  93. package/dist/parcel/parcel.api.d.ts.map +1 -0
  94. package/dist/parcel/parcel.interface.d.ts +26 -5
  95. package/dist/parcel/parcel.interface.d.ts.map +1 -1
  96. package/dist/parcel/parcel.service.d.ts +38 -0
  97. package/dist/parcel/parcel.service.d.ts.map +1 -0
  98. package/dist/parcel/storage-provider-registry.d.ts +17 -0
  99. package/dist/parcel/storage-provider-registry.d.ts.map +1 -0
  100. package/dist/parcel/storage-provider.types.d.ts +31 -0
  101. package/dist/parcel/storage-provider.types.d.ts.map +1 -0
  102. package/dist/preload.d.ts +7 -0
  103. package/dist/preload.d.ts.map +1 -0
  104. package/dist/preload.js +47 -0
  105. package/dist/preload.js.map +1 -0
  106. package/dist/repo/repo-context.utils.d.ts.map +1 -1
  107. package/dist/repo/repo-manager.d.ts +14 -3
  108. package/dist/repo/repo-manager.d.ts.map +1 -1
  109. package/dist/repo/repo.api.d.ts +1 -1
  110. package/dist/repo/repo.api.d.ts.map +1 -1
  111. package/dist/repo/repo.interface.d.ts +1 -1
  112. package/dist/repo/repo.interface.d.ts.map +1 -1
  113. package/dist/repo/repo.script-loader.d.ts +5 -5
  114. package/dist/repo/repo.script-loader.d.ts.map +1 -1
  115. package/dist/service/base.interface.d.ts +54 -57
  116. package/dist/service/base.interface.d.ts.map +1 -1
  117. package/dist/service/index.d.ts +21 -0
  118. package/dist/service/index.d.ts.map +1 -0
  119. package/dist/service/service.api.d.ts +503 -0
  120. package/dist/service/service.api.d.ts.map +1 -0
  121. package/dist/service/service.interface.d.ts +36 -9
  122. package/dist/service/service.interface.d.ts.map +1 -1
  123. package/dist/shared/http/fetch-retry.d.ts +21 -0
  124. package/dist/shared/http/fetch-retry.d.ts.map +1 -0
  125. package/dist/shared/log/create-logger.d.ts +27 -0
  126. package/dist/shared/log/create-logger.d.ts.map +1 -0
  127. package/dist/shared/log/enable-log-persist.d.ts +28 -0
  128. package/dist/shared/log/enable-log-persist.d.ts.map +1 -0
  129. package/dist/shared/log/index.d.ts +10 -0
  130. package/dist/shared/log/index.d.ts.map +1 -0
  131. package/dist/shared/log/log-manager.d.ts +37 -60
  132. package/dist/shared/log/log-manager.d.ts.map +1 -1
  133. package/dist/shared/log/log-persist-batch-id.d.ts +13 -0
  134. package/dist/shared/log/log-persist-batch-id.d.ts.map +1 -0
  135. package/dist/shared/log/log-persist-flush.d.ts +8 -0
  136. package/dist/shared/log/log-persist-flush.d.ts.map +1 -0
  137. package/dist/shared/log/log-persist-hook.d.ts +6 -0
  138. package/dist/shared/log/log-persist-hook.d.ts.map +1 -0
  139. package/dist/shared/log/log-persist-logger.d.ts +15 -0
  140. package/dist/shared/log/log-persist-logger.d.ts.map +1 -0
  141. package/dist/shared/log/log-persist-registry.d.ts +17 -0
  142. package/dist/shared/log/log-persist-registry.d.ts.map +1 -0
  143. package/dist/shared/log/log-persist.config.d.ts +10 -0
  144. package/dist/shared/log/log-persist.config.d.ts.map +1 -0
  145. package/dist/shared/log/log-persist.d.ts +55 -0
  146. package/dist/shared/log/log-persist.d.ts.map +1 -0
  147. package/dist/shared/log/log-persist.interface.d.ts +116 -0
  148. package/dist/shared/log/log-persist.interface.d.ts.map +1 -0
  149. package/dist/shared/log/log-scope.d.ts +56 -0
  150. package/dist/shared/log/log-scope.d.ts.map +1 -0
  151. package/dist/shared/utils/fetch-url.d.ts +3 -0
  152. package/dist/shared/utils/fetch-url.d.ts.map +1 -0
  153. package/dist/shared/utils/network-error.d.ts +14 -0
  154. package/dist/shared/utils/network-error.d.ts.map +1 -0
  155. package/dist/shared/utils/safe-file-name.d.ts +14 -0
  156. package/dist/shared/utils/safe-file-name.d.ts.map +1 -0
  157. package/dist/shared/utils/sha256.d.ts +3 -0
  158. package/dist/shared/utils/sha256.d.ts.map +1 -0
  159. package/dist/supabase.d.ts +7 -2
  160. package/dist/supabase.d.ts.map +1 -1
  161. package/dist/task/index.d.ts +16 -0
  162. package/dist/task/index.d.ts.map +1 -0
  163. package/dist/task/local-task-registry.d.ts +11 -1
  164. package/dist/task/local-task-registry.d.ts.map +1 -1
  165. package/dist/task/task-manager.d.ts +21 -11
  166. package/dist/task/task-manager.d.ts.map +1 -1
  167. package/dist/task/task-node.d.ts +19 -0
  168. package/dist/task/task-node.d.ts.map +1 -0
  169. package/dist/task/task-post-validated.api.d.ts +19 -0
  170. package/dist/task/task-post-validated.api.d.ts.map +1 -0
  171. package/dist/task/task-post.api.d.ts +54 -0
  172. package/dist/task/task-post.api.d.ts.map +1 -0
  173. package/dist/task/task-queue.d.ts +7 -0
  174. package/dist/task/task-queue.d.ts.map +1 -0
  175. package/dist/task/task-repo-context.d.ts +2 -0
  176. package/dist/task/task-repo-context.d.ts.map +1 -1
  177. package/dist/task/task-repo-validation.d.ts +46 -0
  178. package/dist/task/task-repo-validation.d.ts.map +1 -0
  179. package/dist/task/task.api.d.ts +5 -47
  180. package/dist/task/task.api.d.ts.map +1 -1
  181. package/dist/task/task.constant.d.ts +4 -0
  182. package/dist/task/task.constant.d.ts.map +1 -0
  183. package/dist/task/task.interface.d.ts +3 -1
  184. package/dist/task/task.interface.d.ts.map +1 -1
  185. package/dist/trigger/trigger-manager.d.ts +25 -0
  186. package/dist/trigger/trigger-manager.d.ts.map +1 -0
  187. package/dist/trigger/trigger-node.d.ts +23 -0
  188. package/dist/trigger/trigger-node.d.ts.map +1 -0
  189. package/dist/trigger/trigger.api.d.ts +140 -0
  190. package/dist/trigger/trigger.api.d.ts.map +1 -0
  191. package/dist/trigger/trigger.constant.d.ts +8 -0
  192. package/dist/trigger/trigger.constant.d.ts.map +1 -0
  193. package/dist/trigger/trigger.interface.d.ts +87 -0
  194. package/dist/trigger/trigger.interface.d.ts.map +1 -0
  195. package/dist/trigger/trigger.utils.d.ts +6 -0
  196. package/dist/trigger/trigger.utils.d.ts.map +1 -0
  197. package/dist/word/word.api.d.ts +1 -1
  198. package/dist/word/word.api.d.ts.map +1 -1
  199. package/dist/word/word.interface.d.ts +2 -2
  200. package/dist/word/word.interface.d.ts.map +1 -1
  201. package/package.json +91 -61
  202. package/src/browser.ts +165 -0
  203. package/src/command/command.api.ts +20 -18
  204. package/src/command/command.interface.ts +2 -3
  205. package/src/core.api.ts +466 -477
  206. package/src/core.interface.ts +63 -62
  207. package/src/core.utils.ts +64 -64
  208. package/src/idea/idea.interface.ts +3 -3
  209. package/src/index.ts +2 -79
  210. package/src/link/link.api.ts +28 -30
  211. package/src/link/link.interface.ts +4 -5
  212. package/src/list/list.api.ts +50 -29
  213. package/src/list/list.interface.ts +3 -4
  214. package/src/node/env/env-parsers.ts +77 -0
  215. package/src/node/env/index.ts +10 -0
  216. package/src/node/env/init-supabase-from-env.ts +38 -0
  217. package/src/node/env/load-env.ts +67 -0
  218. package/src/node/env/project-root.ts +34 -0
  219. package/src/node/env/public-base-url.ts +18 -0
  220. package/src/node/env/require-env.ts +15 -0
  221. package/src/node/fs/json-state-store.ts +97 -0
  222. package/src/node/fs/read-source-file.ts +75 -0
  223. package/src/node/node-liveness.ts +80 -0
  224. package/src/node/node-runtime.base.ts +481 -0
  225. package/src/node/node.api.ts +12 -11
  226. package/src/node/node.interface.ts +1 -8
  227. package/src/node/node.utils.ts +1 -1
  228. package/src/node/preload/run-service-preload.ts +48 -0
  229. package/src/node/preload/service-preload.interface.ts +14 -0
  230. package/src/node/process/index.ts +8 -0
  231. package/src/node/process/managed-child-processes.ts +121 -0
  232. package/src/node/process/process-spawn.ts +61 -0
  233. package/src/node/readiness/index.ts +20 -0
  234. package/src/node/readiness/poll-until.ts +27 -0
  235. package/src/node/readiness/readiness-checks.ts +79 -0
  236. package/src/node/readiness/readiness.types.ts +13 -0
  237. package/src/node/readiness/run-readiness-checks.ts +20 -0
  238. package/src/node/readiness/service-ready-gate.ts +65 -0
  239. package/src/node.ts +153 -0
  240. package/src/parcel/chunk-fetch-registry.ts +96 -0
  241. package/src/parcel/chunk-url.utils.ts +30 -0
  242. package/src/parcel/parcel-manager.ts +431 -173
  243. package/src/parcel/parcel.api.ts +103 -0
  244. package/src/parcel/parcel.interface.ts +44 -23
  245. package/src/parcel/parcel.service.ts +79 -0
  246. package/src/parcel/storage-provider-registry.ts +49 -0
  247. package/src/parcel/storage-provider.types.ts +45 -0
  248. package/src/preload.ts +7 -0
  249. package/src/repo/repo-context.utils.ts +3 -4
  250. package/src/repo/repo-manager.ts +54 -39
  251. package/src/repo/repo.api.ts +5 -5
  252. package/src/repo/repo.interface.ts +1 -2
  253. package/src/repo/repo.script-loader.ts +16 -20
  254. package/src/service/base.interface.ts +81 -90
  255. package/src/service/index.ts +173 -0
  256. package/src/service/service.api.ts +294 -0
  257. package/src/service/service.interface.ts +49 -17
  258. package/src/shared/http/fetch-retry.ts +145 -0
  259. package/src/shared/log/create-logger.ts +51 -0
  260. package/src/shared/log/enable-log-persist.ts +225 -0
  261. package/src/shared/log/index.ts +31 -0
  262. package/src/shared/log/log-manager.ts +112 -121
  263. package/src/shared/log/log-persist-batch-id.ts +43 -0
  264. package/src/shared/log/log-persist-flush.ts +128 -0
  265. package/src/shared/log/log-persist-hook.ts +13 -0
  266. package/src/shared/log/log-persist-logger.ts +33 -0
  267. package/src/shared/log/log-persist-registry.ts +109 -0
  268. package/src/shared/log/log-persist.config.ts +97 -0
  269. package/src/shared/log/log-persist.interface.ts +132 -0
  270. package/src/shared/log/log-persist.ts +704 -0
  271. package/src/shared/log/log-scope.ts +123 -0
  272. package/src/shared/utils/config-path.utils.ts +1 -1
  273. package/src/shared/utils/fetch-url.ts +13 -0
  274. package/src/shared/utils/network-error.ts +152 -0
  275. package/src/shared/utils/safe-file-name.ts +37 -0
  276. package/src/shared/utils/sha256.ts +15 -0
  277. package/src/supabase.ts +125 -119
  278. package/src/task/index.ts +45 -0
  279. package/src/task/local-task-registry.ts +115 -36
  280. package/src/task/task-manager.ts +101 -113
  281. package/src/task/task-node.ts +302 -0
  282. package/src/task/task-post-validated.api.ts +47 -0
  283. package/src/task/task-post.api.ts +99 -0
  284. package/src/task/task-queue.ts +18 -0
  285. package/src/task/task-repo-context.ts +4 -1
  286. package/src/task/task-repo-validation.ts +169 -0
  287. package/src/task/task.api.ts +68 -92
  288. package/src/task/task.constant.ts +4 -0
  289. package/src/task/task.interface.ts +6 -7
  290. package/src/trigger/trigger-manager.ts +287 -0
  291. package/src/trigger/trigger-node.ts +80 -0
  292. package/src/trigger/trigger.api.ts +166 -0
  293. package/src/trigger/trigger.constant.ts +10 -0
  294. package/src/trigger/trigger.interface.ts +100 -0
  295. package/src/trigger/trigger.utils.ts +56 -0
  296. package/src/word/word.api.ts +28 -30
  297. package/src/word/word.interface.ts +3 -4
  298. package/dist/auth/auth.api.d.ts +0 -28
  299. package/dist/auth/auth.api.d.ts.map +0 -1
  300. package/dist/auth/auth.api.js +0 -51
  301. package/dist/auth/auth.api.js.map +0 -1
  302. package/dist/command/command.api.js +0 -58
  303. package/dist/command/command.api.js.map +0 -1
  304. package/dist/command/command.interface.js +0 -9
  305. package/dist/command/command.interface.js.map +0 -1
  306. package/dist/core.api.js +0 -412
  307. package/dist/core.api.js.map +0 -1
  308. package/dist/core.interface.js +0 -46
  309. package/dist/core.interface.js.map +0 -1
  310. package/dist/core.utils.js +0 -81
  311. package/dist/core.utils.js.map +0 -1
  312. package/dist/feed/feed.interface.d.ts +0 -27
  313. package/dist/feed/feed.interface.d.ts.map +0 -1
  314. package/dist/feed/feed.interface.js +0 -17
  315. package/dist/feed/feed.interface.js.map +0 -1
  316. package/dist/file/file-manager.d.ts +0 -24
  317. package/dist/file/file-manager.d.ts.map +0 -1
  318. package/dist/file/file-manager.js +0 -109
  319. package/dist/file/file-manager.js.map +0 -1
  320. package/dist/file/file.api.d.ts +0 -15
  321. package/dist/file/file.api.d.ts.map +0 -1
  322. package/dist/file/file.api.js +0 -30
  323. package/dist/file/file.api.js.map +0 -1
  324. package/dist/file/file.interface.d.ts +0 -25
  325. package/dist/file/file.interface.d.ts.map +0 -1
  326. package/dist/file/file.interface.js +0 -9
  327. package/dist/file/file.interface.js.map +0 -1
  328. package/dist/file-list/file-list.api.d.ts +0 -15
  329. package/dist/file-list/file-list.api.d.ts.map +0 -1
  330. package/dist/file-list/file-list.api.js +0 -54
  331. package/dist/file-list/file-list.api.js.map +0 -1
  332. package/dist/file-list/file-list.interface.d.ts +0 -22
  333. package/dist/file-list/file-list.interface.d.ts.map +0 -1
  334. package/dist/file-list/file-list.interface.js +0 -5
  335. package/dist/file-list/file-list.interface.js.map +0 -1
  336. package/dist/idea/idea.interface.js +0 -15
  337. package/dist/idea/idea.interface.js.map +0 -1
  338. package/dist/index.js +0 -42
  339. package/dist/index.js.map +0 -1
  340. package/dist/link/link.api.js +0 -30
  341. package/dist/link/link.api.js.map +0 -1
  342. package/dist/link/link.interface.js +0 -7
  343. package/dist/link/link.interface.js.map +0 -1
  344. package/dist/list/list.api.js +0 -30
  345. package/dist/list/list.api.js.map +0 -1
  346. package/dist/list/list.interface.js +0 -6
  347. package/dist/list/list.interface.js.map +0 -1
  348. package/dist/node/node-manager.d.ts +0 -48
  349. package/dist/node/node-manager.d.ts.map +0 -1
  350. package/dist/node/node-manager.js +0 -619
  351. package/dist/node/node-manager.js.map +0 -1
  352. package/dist/node/node-task.preset.d.ts +0 -1
  353. package/dist/node/node-task.preset.d.ts.map +0 -1
  354. package/dist/node/node-task.preset.js +0 -14
  355. package/dist/node/node-task.preset.js.map +0 -1
  356. package/dist/node/node.api.js +0 -100
  357. package/dist/node/node.api.js.map +0 -1
  358. package/dist/node/node.interface.js +0 -19
  359. package/dist/node/node.interface.js.map +0 -1
  360. package/dist/node/node.utils.js +0 -36
  361. package/dist/node/node.utils.js.map +0 -1
  362. package/dist/parcel/parcel-manager.js +0 -156
  363. package/dist/parcel/parcel-manager.js.map +0 -1
  364. package/dist/parcel/parcel.interface.js +0 -11
  365. package/dist/parcel/parcel.interface.js.map +0 -1
  366. package/dist/question-list/question-list.api.d.ts +0 -13
  367. package/dist/question-list/question-list.api.d.ts.map +0 -1
  368. package/dist/question-list/question-list.api.js +0 -35
  369. package/dist/question-list/question-list.api.js.map +0 -1
  370. package/dist/question-list/question-list.interface.d.ts +0 -18
  371. package/dist/question-list/question-list.interface.d.ts.map +0 -1
  372. package/dist/question-list/question-list.interface.js +0 -5
  373. package/dist/question-list/question-list.interface.js.map +0 -1
  374. package/dist/repo/repo-context.utils.js +0 -81
  375. package/dist/repo/repo-context.utils.js.map +0 -1
  376. package/dist/repo/repo-manager.js +0 -156
  377. package/dist/repo/repo-manager.js.map +0 -1
  378. package/dist/repo/repo.api.js +0 -40
  379. package/dist/repo/repo.api.js.map +0 -1
  380. package/dist/repo/repo.interface.js +0 -8
  381. package/dist/repo/repo.interface.js.map +0 -1
  382. package/dist/repo/repo.script-loader.js +0 -108
  383. package/dist/repo/repo.script-loader.js.map +0 -1
  384. package/dist/review/review.api.d.ts +0 -14
  385. package/dist/review/review.api.d.ts.map +0 -1
  386. package/dist/review/review.api.js +0 -133
  387. package/dist/review/review.api.js.map +0 -1
  388. package/dist/review/review.interface.d.ts +0 -24
  389. package/dist/review/review.interface.d.ts.map +0 -1
  390. package/dist/review/review.interface.js +0 -10
  391. package/dist/review/review.interface.js.map +0 -1
  392. package/dist/review-v2/apis/post-review-setting.api.d.ts +0 -12
  393. package/dist/review-v2/apis/post-review-setting.api.d.ts.map +0 -1
  394. package/dist/review-v2/apis/post-review-setting.api.js +0 -27
  395. package/dist/review-v2/apis/post-review-setting.api.js.map +0 -1
  396. package/dist/review-v2/apis/post-review.api.d.ts +0 -13
  397. package/dist/review-v2/apis/post-review.api.d.ts.map +0 -1
  398. package/dist/review-v2/apis/post-review.api.js +0 -46
  399. package/dist/review-v2/apis/post-review.api.js.map +0 -1
  400. package/dist/review-v2/review-setting.interface.d.ts +0 -23
  401. package/dist/review-v2/review-setting.interface.d.ts.map +0 -1
  402. package/dist/review-v2/review-setting.interface.js +0 -5
  403. package/dist/review-v2/review-setting.interface.js.map +0 -1
  404. package/dist/review-v2/review.interface.d.ts +0 -20
  405. package/dist/review-v2/review.interface.d.ts.map +0 -1
  406. package/dist/review-v2/review.interface.js +0 -5
  407. package/dist/review-v2/review.interface.js.map +0 -1
  408. package/dist/service/api.interface.d.ts +0 -35
  409. package/dist/service/api.interface.d.ts.map +0 -1
  410. package/dist/service/api.interface.js +0 -12
  411. package/dist/service/api.interface.js.map +0 -1
  412. package/dist/service/base.interface.js +0 -7
  413. package/dist/service/base.interface.js.map +0 -1
  414. package/dist/service/service.interface.js +0 -11
  415. package/dist/service/service.interface.js.map +0 -1
  416. package/dist/shared/log/create-api-logger.d.ts +0 -17
  417. package/dist/shared/log/create-api-logger.d.ts.map +0 -1
  418. package/dist/shared/log/create-api-logger.js +0 -15
  419. package/dist/shared/log/create-api-logger.js.map +0 -1
  420. package/dist/shared/log/log-manager.js +0 -218
  421. package/dist/shared/log/log-manager.js.map +0 -1
  422. package/dist/shared/utils/config-path.utils.js +0 -85
  423. package/dist/shared/utils/config-path.utils.js.map +0 -1
  424. package/dist/shared/utils/error.utils.js +0 -15
  425. package/dist/shared/utils/error.utils.js.map +0 -1
  426. package/dist/shared/utils/id.utils.js +0 -5
  427. package/dist/shared/utils/id.utils.js.map +0 -1
  428. package/dist/supabase.js +0 -100
  429. package/dist/supabase.js.map +0 -1
  430. package/dist/task/local-task-registry.js +0 -153
  431. package/dist/task/local-task-registry.js.map +0 -1
  432. package/dist/task/task-manager.js +0 -217
  433. package/dist/task/task-manager.js.map +0 -1
  434. package/dist/task/task-repo-context.js +0 -12
  435. package/dist/task/task-repo-context.js.map +0 -1
  436. package/dist/task/task.api.js +0 -351
  437. package/dist/task/task.api.js.map +0 -1
  438. package/dist/task/task.interface.js +0 -36
  439. package/dist/task/task.interface.js.map +0 -1
  440. package/dist/task/task.utils.js +0 -2
  441. package/dist/task/task.utils.js.map +0 -1
  442. package/dist/word/word.api.js +0 -30
  443. package/dist/word/word.api.js.map +0 -1
  444. package/dist/word/word.interface.js +0 -6
  445. package/dist/word/word.interface.js.map +0 -1
  446. package/src/auth/auth.api.ts +0 -87
  447. package/src/feed/feed.interface.ts +0 -33
  448. package/src/file/file-manager.ts +0 -145
  449. package/src/file/file.api.ts +0 -43
  450. package/src/file/file.interface.ts +0 -30
  451. package/src/file-list/file-list.api.ts +0 -64
  452. package/src/file-list/file-list.interface.ts +0 -24
  453. package/src/node/node-manager.ts +0 -673
  454. package/src/node/node-task.preset.ts +0 -13
  455. package/src/question-list/question-list.api.ts +0 -42
  456. package/src/question-list/question-list.interface.ts +0 -21
  457. package/src/review/review.api.ts +0 -145
  458. package/src/review/review.interface.ts +0 -26
  459. package/src/review-v2/apis/post-review-setting.api.ts +0 -35
  460. package/src/review-v2/apis/post-review.api.ts +0 -59
  461. package/src/review-v2/review-setting.interface.ts +0 -26
  462. package/src/review-v2/review.interface.ts +0 -23
  463. package/src/service/api.interface.ts +0 -47
  464. package/src/shared/log/create-api-logger.ts +0 -25
@@ -1,8 +1,18 @@
1
- import { createTarget, getPossibleTarget, QueryFilter, updateTargetDetails, validateWithSchema, isOptimisticLockError, OPTIMISTIC_LOCK_FAILED_MESSAGE } from "../core.api";
2
- import { generateResponse, type SupabaseResponse } from "../core.interface";
3
- import { createApiLogger, type LoggerWithContext } from "../shared/log/log-manager";
4
1
  import { z } from "zod";
5
- import { CategoryTask, ResultCode, Task, TaskDetails, TaskStatus, TaskStatusAction } from "./task.interface";
2
+ import {
3
+ getTargetList,
4
+ isOptimisticLockError,
5
+ OPTIMISTIC_LOCK_ERROR_CODE,
6
+ OPTIMISTIC_LOCK_FAILED_MESSAGE,
7
+ type QueryFilter,
8
+ updateTargetDetails,
9
+ validateWithSchema,
10
+ } from "../core.api";
11
+ import { generateResponse, type SupabaseResponse } from "../core.interface";
12
+ import { createLogger, type LoggerWithScope } from "../shared/log";
13
+ import { getErrorMessage } from "../shared/utils/error.utils";
14
+ import { LOG_TOPIC_TASK } from "./task.constant";
15
+ import { CategoryTask, ResultCode, type Task, type TaskDetails, TaskStatus, TaskStatusAction } from "./task.interface";
6
16
 
7
17
  const TASK_STATUS_FIELD = "details->>status" as const;
8
18
  const TASK_NODE_ID_FIELD = "details->>nodeId" as const;
@@ -44,8 +54,9 @@ const TASK_NODE_ID_FIELD = "details->>nodeId" as const;
44
54
 
45
55
  const taskIdSchema = z.string().trim().min(1);
46
56
  const nodeIdSchema = z.string().trim().min(1);
47
- /** Optional — orchestrator (e.g. NodeManager loop) passes its trace to correlate logs. */
57
+ /** Optional — orchestrator (e.g. TaskNode loop) passes its trace to correlate logs. */
48
58
  const traceIdSchema = z.string().trim().min(1).optional();
59
+ const _traceParentIdSchema = z.string().trim().min(1).nullable().optional();
49
60
 
50
61
  const patchChangeTaskStatusBaseSchema = {
51
62
  id: taskIdSchema,
@@ -107,25 +118,6 @@ export const patchClaimTaskSchema = z.object({
107
118
 
108
119
  export type PatchClaimTaskPayload = z.infer<typeof patchClaimTaskSchema>;
109
120
 
110
- /** Initial status for a new task — OPEN (draft) or TODO (claimable by workers). */
111
- const postTaskInitialStatusSchema = z
112
- .union([z.literal(TaskStatus.OPEN), z.literal(TaskStatus.TODO)])
113
- .optional()
114
- .default(TaskStatus.TODO);
115
-
116
- export const postTaskSchema = z.object({
117
- name: z.string().trim().min(1),
118
- /** Task type key — matches `task.value`, {@link patchClaimTask}, {@link Repo.value}, and local Repo registry. */
119
- value: z.string().trim().min(1),
120
- params: z.unknown(),
121
- taskStatus: postTaskInitialStatusSchema,
122
- tagList: z.array(z.string()).optional().default([]),
123
- extra: z.string().optional(),
124
- traceId: traceIdSchema,
125
- });
126
-
127
- export type PostTaskPayload = z.infer<typeof postTaskSchema>;
128
-
129
121
  // ─── Optimistic lock helpers ─────────────────────────────────────────────────
130
122
 
131
123
  function lockOnStatus(...allowed: TaskStatus[]): QueryFilter[] {
@@ -178,20 +170,20 @@ async function transitionTask({
178
170
  }
179
171
 
180
172
  function logTaskTransition(
181
- logger: LoggerWithContext,
173
+ logger: LoggerWithScope,
182
174
  action: TaskStatusAction | "patchTaskProgress" | "patchClaimTask",
183
175
  task: Task,
184
- context?: Record<string, unknown>
176
+ data?: Record<string, unknown>,
185
177
  ): void {
186
- logger.info("任务状态迁移成功", {
187
- topic: "task",
188
- context: {
178
+ logger.debug("任務狀態遷移成功", {
179
+ topic: LOG_TOPIC_TASK,
180
+ data: {
189
181
  action,
190
182
  taskId: task.id,
191
183
  taskValue: task.value,
192
184
  status: task.details.status,
193
185
  nodeId: task.details.nodeId,
194
- ...context,
186
+ ...data,
195
187
  },
196
188
  });
197
189
  }
@@ -222,9 +214,9 @@ async function claimTaskById({
222
214
 
223
215
  export const patchChangeTaskStatus = validateWithSchema(
224
216
  patchChangeTaskStatusSchema,
225
- "patchChangeTaskStatusSchema"
217
+ "patchChangeTaskStatusSchema",
226
218
  )(async (params) => {
227
- const logger = createApiLogger("patchChangeTaskStatus", { traceId: params.traceId });
219
+ const logger = createLogger({ module: "patchChangeTaskStatus", traceId: params.traceId });
228
220
  const { id, action, extra } = params;
229
221
  const updateExtraFn = extra == null ? undefined : () => extra;
230
222
 
@@ -314,7 +306,9 @@ export const patchChangeTaskStatus = validateWithSchema(
314
306
  }
315
307
  default: {
316
308
  const _exhaustive: never = action;
317
- throw new Error(`[patchChangeTaskStatus] Unknown action: ${_exhaustive}`);
309
+ const message = `[patchChangeTaskStatus] Unknown action: ${String(_exhaustive)}`;
310
+ logger.error(message, { topic: "task", data: { action: String(_exhaustive) } });
311
+ return generateResponse.error(message);
318
312
  }
319
313
  }
320
314
  });
@@ -324,9 +318,9 @@ export const patchChangeTaskStatus = validateWithSchema(
324
318
  /** Update progress on a DOING task; only the owning node may write (see `lockOnDoingOwner`). */
325
319
  export const patchTaskProgress = validateWithSchema(
326
320
  patchTaskProgressSchema,
327
- "patchTaskProgressSchema"
321
+ "patchTaskProgressSchema",
328
322
  )(async ({ id, progress, nodeId, traceId }) => {
329
- const logger = createApiLogger("patchTaskProgress", { traceId, nodeId });
323
+ const logger = createLogger({ module: "patchTaskProgress", traceId, labels: { nodeId } });
330
324
  const data = await transitionTask({
331
325
  id,
332
326
  optimisticLockFilterList: lockOnDoingOwner(nodeId),
@@ -344,86 +338,68 @@ export const patchTaskProgress = validateWithSchema(
344
338
  /**
345
339
  * Discover and claim one TODO task for this node.
346
340
  *
347
- * Flow: filter by `availableTaskList` → {@link claimTaskById} (same as `action: CLAIM`).
341
+ * Flow: oldest TODO in `availableTaskList` (FIFO by `created_at`) → {@link claimTaskById}.
348
342
  * Equivalent to `patchChangeTaskStatus({ id, action: CLAIM, nodeId })` when `id` is already known.
349
343
  *
350
344
  * Returns `data: null` when no TODO task matches.
351
- * Optimistic lock conflicts return `{ error }` with `code: "OPTIMISTIC_LOCK"` (not thrown).
345
+ * Optimistic lock conflicts return `{ error, code: OPTIMISTIC_LOCK_ERROR_CODE }` (not thrown).
352
346
  */
353
347
  export const patchClaimTask = validateWithSchema(
354
348
  patchClaimTaskSchema,
355
- "patchClaimTaskSchema"
349
+ "patchClaimTaskSchema",
356
350
  )(async ({ nodeId, availableTaskList, traceId }): Promise<SupabaseResponse<Task | null>> => {
357
- const logger = createApiLogger("patchClaimTask", { traceId, nodeId });
351
+ const logger = createLogger({ module: "patchClaimTask", traceId, labels: { nodeId } });
358
352
 
353
+ let todoTask: Task;
359
354
  try {
360
- const { data: possibleTask } = await getPossibleTarget({
355
+ const { data: taskCandidates } = await getTargetList<Task>({
356
+ category: CategoryTask.TASK,
361
357
  filterList: [
362
- { field: "category", operator: "eq", value: CategoryTask.TASK },
363
358
  { field: TASK_STATUS_FIELD, operator: "eq", value: TaskStatus.TODO },
364
359
  { field: "value", operator: "in", value: availableTaskList },
365
360
  ],
361
+ limit: 1,
362
+ orderBy: { field: "created_at", ascending: true },
366
363
  });
367
-
364
+ const possibleTask = taskCandidates?.[0] ?? null;
368
365
  if (possibleTask == null) {
369
366
  return generateResponse.success(null);
370
367
  }
368
+ todoTask = possibleTask;
369
+ } catch (error) {
370
+ const message = getErrorMessage(error);
371
+ logger.error("獲取 TODO 任務失敗", { topic: LOG_TOPIC_TASK, data: { error: message, availableTaskList } });
372
+ return generateResponse.error(message) as SupabaseResponse<Task | null>;
373
+ }
371
374
 
372
- const todoTask = possibleTask as Task;
375
+ const taskLogger = createLogger({
376
+ module: "patchClaimTask",
377
+ traceId,
378
+ traceParentId: todoTask.details.traceId,
379
+ labels: { nodeId },
380
+ });
381
+
382
+ try {
373
383
  const data = await claimTaskById({ taskId: todoTask.id, nodeId });
374
- logTaskTransition(logger, "patchClaimTask", data);
384
+ logTaskTransition(taskLogger, "patchClaimTask", data);
375
385
  return generateResponse.success(data);
376
386
  } catch (error) {
377
387
  if (isOptimisticLockError(error)) {
378
- logger.debug("認領競爭失敗,本輪無可認領任務", { topic: "task" });
379
- return generateResponse.error(OPTIMISTIC_LOCK_FAILED_MESSAGE, undefined, "OPTIMISTIC_LOCK") as SupabaseResponse<Task | null>;
388
+ taskLogger.debug("認領競爭失敗,任務已被其他節點認領", {
389
+ topic: LOG_TOPIC_TASK,
390
+ data: { taskId: todoTask.id, taskTypeKey: todoTask.value },
391
+ });
392
+ return generateResponse.error(
393
+ OPTIMISTIC_LOCK_FAILED_MESSAGE,
394
+ undefined,
395
+ OPTIMISTIC_LOCK_ERROR_CODE,
396
+ ) as SupabaseResponse<Task | null>;
380
397
  }
381
- const message = error instanceof Error ? error.message : String(error);
382
- logger.error("認領任務失敗", { topic: "task", context: { error: message } });
398
+ const message = getErrorMessage(error);
399
+ taskLogger.error("認領任務失敗", {
400
+ topic: LOG_TOPIC_TASK,
401
+ data: { error: message, taskId: todoTask.id, taskTypeKey: todoTask.value },
402
+ });
383
403
  return generateResponse.error(message) as SupabaseResponse<Task | null>;
384
404
  }
385
405
  });
386
-
387
- // ─── postTask ────────────────────────────────────────────────────────────────
388
-
389
- /**
390
- * Create a task row (scheduler / admin).
391
- *
392
- * `taskStatus` defaults to **TODO** (worker-claimable). Pass **OPEN** for draft tasks
393
- * that require {@link patchChangeTaskStatus} `publish` before workers can claim.
394
- */
395
- export const postTask = validateWithSchema(
396
- postTaskSchema,
397
- "postTaskSchema"
398
- )(async ({ name, value, params, taskStatus, tagList, extra, traceId }) => {
399
- const logger = createApiLogger("postTask", { traceId });
400
-
401
- const result = await createTarget<Task, PostTaskPayload>({
402
- payload: { name, value, params, taskStatus, tagList, extra, traceId },
403
- createFn: () => ({
404
- name,
405
- value,
406
- category: CategoryTask.TASK,
407
- tagList,
408
- extra,
409
- details: {
410
- manifestVersion: 0,
411
- status: taskStatus,
412
- params,
413
- progress: 0,
414
- nodeId: null,
415
- },
416
- }),
417
- });
418
-
419
- logger.info("任務已創建", {
420
- topic: "task",
421
- context: {
422
- taskId: result.data?.id,
423
- taskTypeKey: value,
424
- status: taskStatus,
425
- },
426
- });
427
-
428
- return result;
429
- });
@@ -0,0 +1,4 @@
1
+ /** Log topic for task domain (`topic` field on structured logs). */
2
+ export const LOG_TOPIC_TASK = "task";
3
+
4
+ export const CRITICAL_UNKNOWN_TASK_TRACE_ID = "CRITICAL_UNKNOWN_TASK_TRACE_ID";
@@ -1,4 +1,4 @@
1
- import { Target } from "../core.interface";
1
+ import type { Target } from "../core.interface";
2
2
 
3
3
  export enum CategoryTask {
4
4
  TASK = "task",
@@ -53,16 +53,15 @@ export interface TaskDetails {
53
53
  /** [0,100] */
54
54
  progress: number;
55
55
  nodeId: null | string;
56
+ /** Task lifecycle correlation id (written at postTask). */
57
+ traceId?: string;
56
58
  result?: {
57
59
  cost: number;
58
60
  code: ResultCode;
59
61
  errorMessage?: string;
60
62
  data?: unknown;
61
- }
62
- };
63
-
64
- // TODO loop condition combination
65
- export interface TaskFlow extends Target {
66
-
63
+ };
67
64
  }
68
65
 
66
+ // TODO loop condition combination
67
+ export interface TaskFlow extends Target {}
@@ -0,0 +1,287 @@
1
+ import type { NodeLoopContext } from "../node/node-runtime.base";
2
+ import { createLogger, createScope, withModule } from "../shared/log";
3
+ import { getErrorMessage } from "../shared/utils/error.utils";
4
+ import {
5
+ LOG_TOPIC_TRIGGER,
6
+ TRIGGER_LOOP_INTERVAL_MS,
7
+ TRIGGER_RUNNER_DEFAULT_RETRY_COUNT,
8
+ TRIGGER_RUNNER_DEFAULT_RETRY_DELAY_MS,
9
+ } from "./trigger.constant";
10
+ import type { RegisterTriggerRunnerOptions, TriggerRunnerContext, TriggerRunnerFn } from "./trigger.interface";
11
+
12
+ export type { RegisterTriggerRunnerOptions, TriggerRunnerContext, TriggerRunnerFn } from "./trigger.interface";
13
+
14
+ interface TriggerRunnerState {
15
+ key: string;
16
+ intervalMs: number;
17
+ fn: TriggerRunnerFn;
18
+ retryCount: number;
19
+ retryDelayMs: number;
20
+ timeoutMs: number | undefined;
21
+ nextRunAt: number;
22
+ running: boolean;
23
+ }
24
+
25
+ const runnerRegistry = new Map<string, TriggerRunnerState>();
26
+ let registrationClosed = false;
27
+
28
+ function normalizeRunnerKey(key: string): string {
29
+ const normalized = key.trim();
30
+ if (normalized.length === 0) {
31
+ throw new Error("[TriggerManager] key must be a non-empty string");
32
+ }
33
+ return normalized;
34
+ }
35
+
36
+ function tryNormalizeRunnerKey(key: string): string | null {
37
+ const normalized = key.trim();
38
+ return normalized.length > 0 ? normalized : null;
39
+ }
40
+
41
+ function validateRunnerOptions(options: RegisterTriggerRunnerOptions): void {
42
+ if (!Number.isFinite(options.intervalMs) || options.intervalMs < 1) {
43
+ throw new Error(`[TriggerManager] intervalMs must be a positive number, got ${options.intervalMs}`);
44
+ }
45
+ const retryCount = options.retryCount ?? TRIGGER_RUNNER_DEFAULT_RETRY_COUNT;
46
+ if (!Number.isInteger(retryCount) || retryCount < 0) {
47
+ throw new Error(`[TriggerManager] retryCount must be a non-negative integer, got ${retryCount}`);
48
+ }
49
+ const initialDelayMs = options.initialDelayMs ?? 0;
50
+ if (!Number.isFinite(initialDelayMs) || initialDelayMs < 0) {
51
+ throw new Error(`[TriggerManager] initialDelayMs must be a non-negative number, got ${initialDelayMs}`);
52
+ }
53
+ const retryDelayMs = options.retryDelayMs ?? TRIGGER_RUNNER_DEFAULT_RETRY_DELAY_MS;
54
+ if (!Number.isFinite(retryDelayMs) || retryDelayMs < 0) {
55
+ throw new Error(`[TriggerManager] retryDelayMs must be a non-negative number, got ${retryDelayMs}`);
56
+ }
57
+ if (options.timeoutMs != null) {
58
+ if (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 1) {
59
+ throw new Error(`[TriggerManager] timeoutMs must be a positive number when set, got ${options.timeoutMs}`);
60
+ }
61
+ }
62
+ }
63
+
64
+ function delay(ms: number): Promise<void> {
65
+ return new Promise((resolve) => setTimeout(resolve, ms));
66
+ }
67
+
68
+ async function invokeRunnerFn(
69
+ fn: TriggerRunnerFn,
70
+ ctx: TriggerRunnerContext,
71
+ timeoutMs: number | undefined,
72
+ ): Promise<void> {
73
+ if (timeoutMs == null) {
74
+ await fn(ctx);
75
+ return;
76
+ }
77
+
78
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
79
+ const timeoutPromise = new Promise<never>((_, reject) => {
80
+ timeoutHandle = setTimeout(() => {
81
+ reject(new Error(`Runner timed out after ${timeoutMs}ms`));
82
+ }, timeoutMs);
83
+ });
84
+
85
+ try {
86
+ await Promise.race([Promise.resolve(fn(ctx)), timeoutPromise]);
87
+ } finally {
88
+ if (timeoutHandle != null) {
89
+ clearTimeout(timeoutHandle);
90
+ }
91
+ }
92
+ }
93
+
94
+ /** In-process registry and tick loop for {@link TriggerNode}. */
95
+ export const TriggerManager = {
96
+ registerRunner(options: RegisterTriggerRunnerOptions): void {
97
+ if (registrationClosed) {
98
+ throw new Error("[TriggerManager] Registration closed — call registerRunner before TriggerNode.start()");
99
+ }
100
+
101
+ const key = normalizeRunnerKey(options.key);
102
+ validateRunnerOptions(options);
103
+ if (typeof options.fn !== "function") {
104
+ throw new Error(`[TriggerManager] fn must be a function (runner key: ${key})`);
105
+ }
106
+ if (runnerRegistry.has(key)) {
107
+ throw new Error(`[TriggerManager] Duplicate runner key: ${key}`);
108
+ }
109
+
110
+ const now = Date.now();
111
+ runnerRegistry.set(key, {
112
+ key,
113
+ intervalMs: options.intervalMs,
114
+ fn: options.fn,
115
+ retryCount: options.retryCount ?? TRIGGER_RUNNER_DEFAULT_RETRY_COUNT,
116
+ retryDelayMs: options.retryDelayMs ?? TRIGGER_RUNNER_DEFAULT_RETRY_DELAY_MS,
117
+ timeoutMs: options.timeoutMs,
118
+ nextRunAt: now + (options.initialDelayMs ?? 0),
119
+ running: false,
120
+ });
121
+ },
122
+
123
+ hasRunner(key: string): boolean {
124
+ const normalized = tryNormalizeRunnerKey(key);
125
+ return normalized != null && runnerRegistry.has(normalized);
126
+ },
127
+
128
+ unregisterRunner(key: string): boolean {
129
+ const normalized = tryNormalizeRunnerKey(key);
130
+ if (normalized == null) {
131
+ return false;
132
+ }
133
+ const runner = runnerRegistry.get(normalized);
134
+ if (runner == null) {
135
+ return false;
136
+ }
137
+ if (runner.running) {
138
+ throw new Error(`[TriggerManager] Cannot unregister running runner: ${normalized}`);
139
+ }
140
+ return runnerRegistry.delete(normalized);
141
+ },
142
+
143
+ getRunnerKeys(): string[] {
144
+ return [...runnerRegistry.keys()];
145
+ },
146
+
147
+ getRunnersBelowLoopInterval(): Array<{ key: string; intervalMs: number }> {
148
+ return [...runnerRegistry.values()]
149
+ .filter((runner) => runner.intervalMs < TRIGGER_LOOP_INTERVAL_MS)
150
+ .map((runner) => ({ key: runner.key, intervalMs: runner.intervalMs }));
151
+ },
152
+
153
+ /** Called by TriggerNode during bootstrap — blocks further registerRunner calls. */
154
+ closeRegistration(): void {
155
+ registrationClosed = true;
156
+ },
157
+
158
+ /** Re-open registration (tests only). */
159
+ _resetRegistrationForTests(): void {
160
+ registrationClosed = false;
161
+ },
162
+
163
+ /**
164
+ * Remove all runners. Throws if any runner is still executing.
165
+ * Wait for in-flight ticks to finish before calling in tests.
166
+ */
167
+ clearRunners(): void {
168
+ for (const runner of runnerRegistry.values()) {
169
+ if (runner.running) {
170
+ throw new Error(`[TriggerManager] Cannot clearRunners while runner is running: ${runner.key}`);
171
+ }
172
+ }
173
+ runnerRegistry.clear();
174
+ registrationClosed = false;
175
+ },
176
+
177
+ async tick(ctx: NodeLoopContext): Promise<void> {
178
+ const { loopTraceId, nodeId } = ctx;
179
+ const loopScope = createScope({ module: "tickRunners", traceId: loopTraceId, labels: { nodeId } });
180
+ const logger = createLogger({ scope: loopScope });
181
+
182
+ const now = Date.now();
183
+ const runners = [...runnerRegistry.values()];
184
+ if (runners.length === 0) {
185
+ logger.debug("無 runner 可調度", { topic: LOG_TOPIC_TRIGGER });
186
+ return;
187
+ }
188
+
189
+ // Overlap: if fn is still running when due, skip that tick (no catch-up / backlog).
190
+ // Safe while intervals are large; missed ticks increase if fn duration exceeds intervalMs.
191
+ const dueRunners = runners.filter((runner) => !runner.running && now >= runner.nextRunAt);
192
+ if (dueRunners.length === 0) {
193
+ logger.debug("本輪無到期 runner", { topic: LOG_TOPIC_TRIGGER });
194
+ return;
195
+ }
196
+
197
+ logger.debug("調度到期 runner", {
198
+ topic: LOG_TOPIC_TRIGGER,
199
+ data: { due: dueRunners.map((r) => r.key) },
200
+ });
201
+
202
+ const results = await Promise.all(dueRunners.map((runner) => runRunner(ctx, runner)));
203
+ const executed = results.filter(Boolean).length;
204
+ if (executed > 0) {
205
+ logger.info("Runner 調度完成", {
206
+ topic: LOG_TOPIC_TRIGGER,
207
+ data: { due: dueRunners.length, executed },
208
+ });
209
+ } else {
210
+ logger.warn("本輪到期 runner 均未成功", {
211
+ topic: LOG_TOPIC_TRIGGER,
212
+ data: {
213
+ due: dueRunners.length,
214
+ runnerKeys: dueRunners.map((r) => r.key),
215
+ },
216
+ });
217
+ }
218
+ },
219
+ };
220
+
221
+ async function runRunner(ctx: NodeLoopContext, runner: TriggerRunnerState): Promise<boolean> {
222
+ const { loopTraceId, nodeId } = ctx;
223
+ if (runner.running) {
224
+ return false;
225
+ }
226
+
227
+ runner.running = true;
228
+ const runnerLogger = createLogger({
229
+ scope: withModule(
230
+ createScope({ module: "runRunner", traceId: loopTraceId, labels: { nodeId, runnerKey: runner.key } }),
231
+ runner.key,
232
+ ),
233
+ });
234
+
235
+ const maxAttempts = 1 + runner.retryCount;
236
+ let succeeded = false;
237
+
238
+ try {
239
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
240
+ try {
241
+ runnerLogger.info("Runner 觸發", {
242
+ topic: LOG_TOPIC_TRIGGER,
243
+ data: { attempt, maxAttempts },
244
+ });
245
+ await invokeRunnerFn(
246
+ runner.fn,
247
+ {
248
+ loopTraceId,
249
+ nodeId,
250
+ runnerKey: runner.key,
251
+ logger: runnerLogger,
252
+ attempt,
253
+ maxAttempts,
254
+ },
255
+ runner.timeoutMs,
256
+ );
257
+ runnerLogger.success("Runner 完成", {
258
+ topic: LOG_TOPIC_TRIGGER,
259
+ data: { attempt, maxAttempts },
260
+ });
261
+ succeeded = true;
262
+ break;
263
+ } catch (error) {
264
+ const message = getErrorMessage(error);
265
+ if (attempt < maxAttempts) {
266
+ runnerLogger.warn("Runner 失敗,準備重試", {
267
+ topic: LOG_TOPIC_TRIGGER,
268
+ data: { attempt, maxAttempts, error: message },
269
+ });
270
+ if (runner.retryDelayMs > 0) {
271
+ await delay(runner.retryDelayMs);
272
+ }
273
+ } else {
274
+ runnerLogger.error("Runner 重試用盡仍失敗", {
275
+ topic: LOG_TOPIC_TRIGGER,
276
+ data: { attempt, maxAttempts, error: message },
277
+ });
278
+ }
279
+ }
280
+ }
281
+ } finally {
282
+ runner.running = false;
283
+ runner.nextRunAt = Date.now() + runner.intervalMs;
284
+ }
285
+
286
+ return succeeded;
287
+ }
@@ -0,0 +1,80 @@
1
+ import { BaseNodeRuntime, LOG_TOPIC_NODE, type NodeLoopContext } from "../node/node-runtime.base";
2
+ import { createLogger, createScope, type LoggerWithScope, LogLevel } from "../shared/log";
3
+ import { LOG_TOPIC_TRIGGER, TRIGGER_LOOP_INTERVAL_MS } from "./trigger.constant";
4
+ import type { TriggerNodeOptions } from "./trigger.interface";
5
+ import { TriggerManager } from "./trigger-manager";
6
+
7
+ /**
8
+ * Local interval scheduler node.
9
+ * Main loop: commands → heartbeat → {@link TriggerManager.tick}.
10
+ *
11
+ * Register runners via {@link TriggerManager.registerRunner} before {@link start}.
12
+ * Does not scan Supabase trigger rows — see `trigger.api.ts` for remote admin APIs.
13
+ *
14
+ * Deploy **one** TriggerNode per logical scheduler — multiple processes duplicate runner work.
15
+ */
16
+ class TriggerNode extends BaseNodeRuntime {
17
+ private readonly requireRunners: boolean;
18
+
19
+ constructor(options?: TriggerNodeOptions) {
20
+ super("triggerNode");
21
+ this.requireRunners = options?.requireRunners ?? false;
22
+ }
23
+
24
+ protected getLoopIntervalMs(): number {
25
+ return TRIGGER_LOOP_INTERVAL_MS;
26
+ }
27
+
28
+ protected loopLoggerMinLevel(): LogLevel {
29
+ return LogLevel.WARN;
30
+ }
31
+
32
+ protected async onBeforeRegisterNode(logger: LoggerWithScope): Promise<void> {
33
+ TriggerManager.closeRegistration();
34
+
35
+ const runnerKeys = TriggerManager.getRunnerKeys();
36
+ if (runnerKeys.length === 0) {
37
+ if (this.requireRunners) {
38
+ throw new Error("[TriggerNode] requireRunners is true but no runners are registered");
39
+ }
40
+ logger.warn("未注册任何 Trigger runner,主循環將空轉", {
41
+ topic: LOG_TOPIC_TRIGGER,
42
+ });
43
+ return;
44
+ }
45
+
46
+ for (const { key, intervalMs } of TriggerManager.getRunnersBelowLoopInterval()) {
47
+ logger.warn("Runner interval 小於主循環 tick 間隔,實際觸發精度受限", {
48
+ topic: LOG_TOPIC_TRIGGER,
49
+ data: {
50
+ runnerKey: key,
51
+ intervalMs,
52
+ loopIntervalMs: TRIGGER_LOOP_INTERVAL_MS,
53
+ },
54
+ });
55
+ }
56
+
57
+ logger.success("Trigger 節點啟動", {
58
+ topic: LOG_TOPIC_TRIGGER,
59
+ data: { runnerKeys },
60
+ });
61
+ }
62
+
63
+ protected async runLoopSteps(ctx: NodeLoopContext, heartbeatOk: boolean): Promise<void> {
64
+ if (!heartbeatOk) {
65
+ const logger = createLogger({
66
+ scope: createScope({
67
+ module: `${this.runtimeModule}-runLoopSteps`,
68
+ traceId: ctx.loopTraceId,
69
+ labels: { nodeId: ctx.nodeId },
70
+ }),
71
+ });
72
+ logger.warn("心跳失敗,本輪跳過 runner", { topic: LOG_TOPIC_NODE });
73
+ return;
74
+ }
75
+ await TriggerManager.tick(ctx);
76
+ }
77
+ }
78
+
79
+ export type { TriggerNodeOptions } from "./trigger.interface";
80
+ export { TriggerNode };