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.
- package/README.md +184 -1
- package/dist/browser.d.ts +60 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +6 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunks/create-logger-DyH3mZ8p.js +1028 -0
- package/dist/chunks/create-logger-DyH3mZ8p.js.map +1 -0
- package/dist/chunks/enable-log-persist-C_bSw6Kx.js +1362 -0
- package/dist/chunks/enable-log-persist-C_bSw6Kx.js.map +1 -0
- package/dist/chunks/word.interface-DLgRobKV.js +1973 -0
- package/dist/chunks/word.interface-DLgRobKV.js.map +1 -0
- package/dist/command/command.api.d.ts +1 -1
- package/dist/command/command.api.d.ts.map +1 -1
- package/dist/command/command.interface.d.ts +1 -1
- package/dist/command/command.interface.d.ts.map +1 -1
- package/dist/core.api.d.ts +10 -6
- package/dist/core.api.d.ts.map +1 -1
- package/dist/core.interface.d.ts +3 -2
- package/dist/core.interface.d.ts.map +1 -1
- package/dist/core.utils.d.ts +1 -1
- package/dist/core.utils.d.ts.map +1 -1
- package/dist/idea/idea.interface.d.ts +1 -1
- package/dist/idea/idea.interface.d.ts.map +1 -1
- package/dist/index.d.ts +2 -48
- package/dist/index.d.ts.map +1 -1
- package/dist/link/link.api.d.ts +1 -1
- package/dist/link/link.api.d.ts.map +1 -1
- package/dist/link/link.interface.d.ts +3 -3
- package/dist/link/link.interface.d.ts.map +1 -1
- package/dist/list/list.api.d.ts +3 -1
- package/dist/list/list.api.d.ts.map +1 -1
- package/dist/list/list.interface.d.ts +2 -2
- package/dist/list/list.interface.d.ts.map +1 -1
- package/dist/node/env/env-parsers.d.ts +19 -0
- package/dist/node/env/env-parsers.d.ts.map +1 -0
- package/dist/node/env/index.d.ts +11 -0
- package/dist/node/env/index.d.ts.map +1 -0
- package/dist/node/env/init-supabase-from-env.d.ts +17 -0
- package/dist/node/env/init-supabase-from-env.d.ts.map +1 -0
- package/dist/node/env/load-env.d.ts +20 -0
- package/dist/node/env/load-env.d.ts.map +1 -0
- package/dist/node/env/project-root.d.ts +11 -0
- package/dist/node/env/project-root.d.ts.map +1 -0
- package/dist/node/env/public-base-url.d.ts +10 -0
- package/dist/node/env/public-base-url.d.ts.map +1 -0
- package/dist/node/env/require-env.d.ts +3 -0
- package/dist/node/env/require-env.d.ts.map +1 -0
- package/dist/node/fs/json-state-store.d.ts +19 -0
- package/dist/node/fs/json-state-store.d.ts.map +1 -0
- package/dist/node/fs/read-source-file.d.ts +19 -0
- package/dist/node/fs/read-source-file.d.ts.map +1 -0
- package/dist/node/node-liveness.d.ts +30 -0
- package/dist/node/node-liveness.d.ts.map +1 -0
- package/dist/node/node-runtime.base.d.ts +60 -0
- package/dist/node/node-runtime.base.d.ts.map +1 -0
- package/dist/node/node.api.d.ts +4 -4
- package/dist/node/node.api.d.ts.map +1 -1
- package/dist/node/node.interface.d.ts +1 -6
- package/dist/node/node.interface.d.ts.map +1 -1
- package/dist/node/preload/run-service-preload.d.ts +14 -0
- package/dist/node/preload/run-service-preload.d.ts.map +1 -0
- package/dist/node/preload/service-preload.interface.d.ts +15 -0
- package/dist/node/preload/service-preload.interface.d.ts.map +1 -0
- package/dist/node/process/index.d.ts +5 -0
- package/dist/node/process/index.d.ts.map +1 -0
- package/dist/node/process/managed-child-processes.d.ts +37 -0
- package/dist/node/process/managed-child-processes.d.ts.map +1 -0
- package/dist/node/process/process-spawn.d.ts +27 -0
- package/dist/node/process/process-spawn.d.ts.map +1 -0
- package/dist/node/readiness/index.d.ts +9 -0
- package/dist/node/readiness/index.d.ts.map +1 -0
- package/dist/node/readiness/poll-until.d.ts +11 -0
- package/dist/node/readiness/poll-until.d.ts.map +1 -0
- package/dist/node/readiness/readiness-checks.d.ts +22 -0
- package/dist/node/readiness/readiness-checks.d.ts.map +1 -0
- package/dist/node/readiness/readiness.types.d.ts +12 -0
- package/dist/node/readiness/readiness.types.d.ts.map +1 -0
- package/dist/node/readiness/run-readiness-checks.d.ts +4 -0
- package/dist/node/readiness/run-readiness-checks.d.ts.map +1 -0
- package/dist/node/readiness/service-ready-gate.d.ts +26 -0
- package/dist/node/readiness/service-ready-gate.d.ts.map +1 -0
- package/dist/node.d.ts +36 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +2483 -0
- package/dist/node.js.map +1 -0
- package/dist/parcel/chunk-fetch-registry.d.ts +14 -0
- package/dist/parcel/chunk-fetch-registry.d.ts.map +1 -0
- package/dist/parcel/chunk-url.utils.d.ts +9 -0
- package/dist/parcel/chunk-url.utils.d.ts.map +1 -0
- package/dist/parcel/parcel-manager.d.ts +44 -20
- package/dist/parcel/parcel-manager.d.ts.map +1 -1
- package/dist/parcel/parcel.api.d.ts +306 -0
- package/dist/parcel/parcel.api.d.ts.map +1 -0
- package/dist/parcel/parcel.interface.d.ts +26 -5
- package/dist/parcel/parcel.interface.d.ts.map +1 -1
- package/dist/parcel/parcel.service.d.ts +38 -0
- package/dist/parcel/parcel.service.d.ts.map +1 -0
- package/dist/parcel/storage-provider-registry.d.ts +17 -0
- package/dist/parcel/storage-provider-registry.d.ts.map +1 -0
- package/dist/parcel/storage-provider.types.d.ts +31 -0
- package/dist/parcel/storage-provider.types.d.ts.map +1 -0
- package/dist/preload.d.ts +7 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +47 -0
- package/dist/preload.js.map +1 -0
- package/dist/repo/repo-context.utils.d.ts.map +1 -1
- package/dist/repo/repo-manager.d.ts +14 -3
- package/dist/repo/repo-manager.d.ts.map +1 -1
- package/dist/repo/repo.api.d.ts +1 -1
- package/dist/repo/repo.api.d.ts.map +1 -1
- package/dist/repo/repo.interface.d.ts +1 -1
- package/dist/repo/repo.interface.d.ts.map +1 -1
- package/dist/repo/repo.script-loader.d.ts +5 -5
- package/dist/repo/repo.script-loader.d.ts.map +1 -1
- package/dist/service/base.interface.d.ts +54 -57
- package/dist/service/base.interface.d.ts.map +1 -1
- package/dist/service/index.d.ts +21 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/service.api.d.ts +503 -0
- package/dist/service/service.api.d.ts.map +1 -0
- package/dist/service/service.interface.d.ts +36 -9
- package/dist/service/service.interface.d.ts.map +1 -1
- package/dist/shared/http/fetch-retry.d.ts +21 -0
- package/dist/shared/http/fetch-retry.d.ts.map +1 -0
- package/dist/shared/log/create-logger.d.ts +27 -0
- package/dist/shared/log/create-logger.d.ts.map +1 -0
- package/dist/shared/log/enable-log-persist.d.ts +28 -0
- package/dist/shared/log/enable-log-persist.d.ts.map +1 -0
- package/dist/shared/log/index.d.ts +10 -0
- package/dist/shared/log/index.d.ts.map +1 -0
- package/dist/shared/log/log-manager.d.ts +37 -60
- package/dist/shared/log/log-manager.d.ts.map +1 -1
- package/dist/shared/log/log-persist-batch-id.d.ts +13 -0
- package/dist/shared/log/log-persist-batch-id.d.ts.map +1 -0
- package/dist/shared/log/log-persist-flush.d.ts +8 -0
- package/dist/shared/log/log-persist-flush.d.ts.map +1 -0
- package/dist/shared/log/log-persist-hook.d.ts +6 -0
- package/dist/shared/log/log-persist-hook.d.ts.map +1 -0
- package/dist/shared/log/log-persist-logger.d.ts +15 -0
- package/dist/shared/log/log-persist-logger.d.ts.map +1 -0
- package/dist/shared/log/log-persist-registry.d.ts +17 -0
- package/dist/shared/log/log-persist-registry.d.ts.map +1 -0
- package/dist/shared/log/log-persist.config.d.ts +10 -0
- package/dist/shared/log/log-persist.config.d.ts.map +1 -0
- package/dist/shared/log/log-persist.d.ts +55 -0
- package/dist/shared/log/log-persist.d.ts.map +1 -0
- package/dist/shared/log/log-persist.interface.d.ts +116 -0
- package/dist/shared/log/log-persist.interface.d.ts.map +1 -0
- package/dist/shared/log/log-scope.d.ts +56 -0
- package/dist/shared/log/log-scope.d.ts.map +1 -0
- package/dist/shared/utils/fetch-url.d.ts +3 -0
- package/dist/shared/utils/fetch-url.d.ts.map +1 -0
- package/dist/shared/utils/network-error.d.ts +14 -0
- package/dist/shared/utils/network-error.d.ts.map +1 -0
- package/dist/shared/utils/safe-file-name.d.ts +14 -0
- package/dist/shared/utils/safe-file-name.d.ts.map +1 -0
- package/dist/shared/utils/sha256.d.ts +3 -0
- package/dist/shared/utils/sha256.d.ts.map +1 -0
- package/dist/supabase.d.ts +7 -2
- package/dist/supabase.d.ts.map +1 -1
- package/dist/task/index.d.ts +16 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/local-task-registry.d.ts +11 -1
- package/dist/task/local-task-registry.d.ts.map +1 -1
- package/dist/task/task-manager.d.ts +21 -11
- package/dist/task/task-manager.d.ts.map +1 -1
- package/dist/task/task-node.d.ts +19 -0
- package/dist/task/task-node.d.ts.map +1 -0
- package/dist/task/task-post-validated.api.d.ts +19 -0
- package/dist/task/task-post-validated.api.d.ts.map +1 -0
- package/dist/task/task-post.api.d.ts +54 -0
- package/dist/task/task-post.api.d.ts.map +1 -0
- package/dist/task/task-queue.d.ts +7 -0
- package/dist/task/task-queue.d.ts.map +1 -0
- package/dist/task/task-repo-context.d.ts +2 -0
- package/dist/task/task-repo-context.d.ts.map +1 -1
- package/dist/task/task-repo-validation.d.ts +46 -0
- package/dist/task/task-repo-validation.d.ts.map +1 -0
- package/dist/task/task.api.d.ts +5 -47
- package/dist/task/task.api.d.ts.map +1 -1
- package/dist/task/task.constant.d.ts +4 -0
- package/dist/task/task.constant.d.ts.map +1 -0
- package/dist/task/task.interface.d.ts +3 -1
- package/dist/task/task.interface.d.ts.map +1 -1
- package/dist/trigger/trigger-manager.d.ts +25 -0
- package/dist/trigger/trigger-manager.d.ts.map +1 -0
- package/dist/trigger/trigger-node.d.ts +23 -0
- package/dist/trigger/trigger-node.d.ts.map +1 -0
- package/dist/trigger/trigger.api.d.ts +140 -0
- package/dist/trigger/trigger.api.d.ts.map +1 -0
- package/dist/trigger/trigger.constant.d.ts +8 -0
- package/dist/trigger/trigger.constant.d.ts.map +1 -0
- package/dist/trigger/trigger.interface.d.ts +87 -0
- package/dist/trigger/trigger.interface.d.ts.map +1 -0
- package/dist/trigger/trigger.utils.d.ts +6 -0
- package/dist/trigger/trigger.utils.d.ts.map +1 -0
- package/dist/word/word.api.d.ts +1 -1
- package/dist/word/word.api.d.ts.map +1 -1
- package/dist/word/word.interface.d.ts +2 -2
- package/dist/word/word.interface.d.ts.map +1 -1
- package/package.json +91 -61
- package/src/browser.ts +165 -0
- package/src/command/command.api.ts +20 -18
- package/src/command/command.interface.ts +2 -3
- package/src/core.api.ts +466 -477
- package/src/core.interface.ts +63 -62
- package/src/core.utils.ts +64 -64
- package/src/idea/idea.interface.ts +3 -3
- package/src/index.ts +2 -79
- package/src/link/link.api.ts +28 -30
- package/src/link/link.interface.ts +4 -5
- package/src/list/list.api.ts +50 -29
- package/src/list/list.interface.ts +3 -4
- package/src/node/env/env-parsers.ts +77 -0
- package/src/node/env/index.ts +10 -0
- package/src/node/env/init-supabase-from-env.ts +38 -0
- package/src/node/env/load-env.ts +67 -0
- package/src/node/env/project-root.ts +34 -0
- package/src/node/env/public-base-url.ts +18 -0
- package/src/node/env/require-env.ts +15 -0
- package/src/node/fs/json-state-store.ts +97 -0
- package/src/node/fs/read-source-file.ts +75 -0
- package/src/node/node-liveness.ts +80 -0
- package/src/node/node-runtime.base.ts +481 -0
- package/src/node/node.api.ts +12 -11
- package/src/node/node.interface.ts +1 -8
- package/src/node/node.utils.ts +1 -1
- package/src/node/preload/run-service-preload.ts +48 -0
- package/src/node/preload/service-preload.interface.ts +14 -0
- package/src/node/process/index.ts +8 -0
- package/src/node/process/managed-child-processes.ts +121 -0
- package/src/node/process/process-spawn.ts +61 -0
- package/src/node/readiness/index.ts +20 -0
- package/src/node/readiness/poll-until.ts +27 -0
- package/src/node/readiness/readiness-checks.ts +79 -0
- package/src/node/readiness/readiness.types.ts +13 -0
- package/src/node/readiness/run-readiness-checks.ts +20 -0
- package/src/node/readiness/service-ready-gate.ts +65 -0
- package/src/node.ts +153 -0
- package/src/parcel/chunk-fetch-registry.ts +96 -0
- package/src/parcel/chunk-url.utils.ts +30 -0
- package/src/parcel/parcel-manager.ts +431 -173
- package/src/parcel/parcel.api.ts +103 -0
- package/src/parcel/parcel.interface.ts +44 -23
- package/src/parcel/parcel.service.ts +79 -0
- package/src/parcel/storage-provider-registry.ts +49 -0
- package/src/parcel/storage-provider.types.ts +45 -0
- package/src/preload.ts +7 -0
- package/src/repo/repo-context.utils.ts +3 -4
- package/src/repo/repo-manager.ts +54 -39
- package/src/repo/repo.api.ts +5 -5
- package/src/repo/repo.interface.ts +1 -2
- package/src/repo/repo.script-loader.ts +16 -20
- package/src/service/base.interface.ts +81 -90
- package/src/service/index.ts +173 -0
- package/src/service/service.api.ts +294 -0
- package/src/service/service.interface.ts +49 -17
- package/src/shared/http/fetch-retry.ts +145 -0
- package/src/shared/log/create-logger.ts +51 -0
- package/src/shared/log/enable-log-persist.ts +225 -0
- package/src/shared/log/index.ts +31 -0
- package/src/shared/log/log-manager.ts +112 -121
- package/src/shared/log/log-persist-batch-id.ts +43 -0
- package/src/shared/log/log-persist-flush.ts +128 -0
- package/src/shared/log/log-persist-hook.ts +13 -0
- package/src/shared/log/log-persist-logger.ts +33 -0
- package/src/shared/log/log-persist-registry.ts +109 -0
- package/src/shared/log/log-persist.config.ts +97 -0
- package/src/shared/log/log-persist.interface.ts +132 -0
- package/src/shared/log/log-persist.ts +704 -0
- package/src/shared/log/log-scope.ts +123 -0
- package/src/shared/utils/config-path.utils.ts +1 -1
- package/src/shared/utils/fetch-url.ts +13 -0
- package/src/shared/utils/network-error.ts +152 -0
- package/src/shared/utils/safe-file-name.ts +37 -0
- package/src/shared/utils/sha256.ts +15 -0
- package/src/supabase.ts +125 -119
- package/src/task/index.ts +45 -0
- package/src/task/local-task-registry.ts +115 -36
- package/src/task/task-manager.ts +101 -113
- package/src/task/task-node.ts +302 -0
- package/src/task/task-post-validated.api.ts +47 -0
- package/src/task/task-post.api.ts +99 -0
- package/src/task/task-queue.ts +18 -0
- package/src/task/task-repo-context.ts +4 -1
- package/src/task/task-repo-validation.ts +169 -0
- package/src/task/task.api.ts +68 -92
- package/src/task/task.constant.ts +4 -0
- package/src/task/task.interface.ts +6 -7
- package/src/trigger/trigger-manager.ts +287 -0
- package/src/trigger/trigger-node.ts +80 -0
- package/src/trigger/trigger.api.ts +166 -0
- package/src/trigger/trigger.constant.ts +10 -0
- package/src/trigger/trigger.interface.ts +100 -0
- package/src/trigger/trigger.utils.ts +56 -0
- package/src/word/word.api.ts +28 -30
- package/src/word/word.interface.ts +3 -4
- package/dist/auth/auth.api.d.ts +0 -28
- package/dist/auth/auth.api.d.ts.map +0 -1
- package/dist/auth/auth.api.js +0 -51
- package/dist/auth/auth.api.js.map +0 -1
- package/dist/command/command.api.js +0 -58
- package/dist/command/command.api.js.map +0 -1
- package/dist/command/command.interface.js +0 -9
- package/dist/command/command.interface.js.map +0 -1
- package/dist/core.api.js +0 -412
- package/dist/core.api.js.map +0 -1
- package/dist/core.interface.js +0 -46
- package/dist/core.interface.js.map +0 -1
- package/dist/core.utils.js +0 -81
- package/dist/core.utils.js.map +0 -1
- package/dist/feed/feed.interface.d.ts +0 -27
- package/dist/feed/feed.interface.d.ts.map +0 -1
- package/dist/feed/feed.interface.js +0 -17
- package/dist/feed/feed.interface.js.map +0 -1
- package/dist/file/file-manager.d.ts +0 -24
- package/dist/file/file-manager.d.ts.map +0 -1
- package/dist/file/file-manager.js +0 -109
- package/dist/file/file-manager.js.map +0 -1
- package/dist/file/file.api.d.ts +0 -15
- package/dist/file/file.api.d.ts.map +0 -1
- package/dist/file/file.api.js +0 -30
- package/dist/file/file.api.js.map +0 -1
- package/dist/file/file.interface.d.ts +0 -25
- package/dist/file/file.interface.d.ts.map +0 -1
- package/dist/file/file.interface.js +0 -9
- package/dist/file/file.interface.js.map +0 -1
- package/dist/file-list/file-list.api.d.ts +0 -15
- package/dist/file-list/file-list.api.d.ts.map +0 -1
- package/dist/file-list/file-list.api.js +0 -54
- package/dist/file-list/file-list.api.js.map +0 -1
- package/dist/file-list/file-list.interface.d.ts +0 -22
- package/dist/file-list/file-list.interface.d.ts.map +0 -1
- package/dist/file-list/file-list.interface.js +0 -5
- package/dist/file-list/file-list.interface.js.map +0 -1
- package/dist/idea/idea.interface.js +0 -15
- package/dist/idea/idea.interface.js.map +0 -1
- package/dist/index.js +0 -42
- package/dist/index.js.map +0 -1
- package/dist/link/link.api.js +0 -30
- package/dist/link/link.api.js.map +0 -1
- package/dist/link/link.interface.js +0 -7
- package/dist/link/link.interface.js.map +0 -1
- package/dist/list/list.api.js +0 -30
- package/dist/list/list.api.js.map +0 -1
- package/dist/list/list.interface.js +0 -6
- package/dist/list/list.interface.js.map +0 -1
- package/dist/node/node-manager.d.ts +0 -48
- package/dist/node/node-manager.d.ts.map +0 -1
- package/dist/node/node-manager.js +0 -619
- package/dist/node/node-manager.js.map +0 -1
- package/dist/node/node-task.preset.d.ts +0 -1
- package/dist/node/node-task.preset.d.ts.map +0 -1
- package/dist/node/node-task.preset.js +0 -14
- package/dist/node/node-task.preset.js.map +0 -1
- package/dist/node/node.api.js +0 -100
- package/dist/node/node.api.js.map +0 -1
- package/dist/node/node.interface.js +0 -19
- package/dist/node/node.interface.js.map +0 -1
- package/dist/node/node.utils.js +0 -36
- package/dist/node/node.utils.js.map +0 -1
- package/dist/parcel/parcel-manager.js +0 -156
- package/dist/parcel/parcel-manager.js.map +0 -1
- package/dist/parcel/parcel.interface.js +0 -11
- package/dist/parcel/parcel.interface.js.map +0 -1
- package/dist/question-list/question-list.api.d.ts +0 -13
- package/dist/question-list/question-list.api.d.ts.map +0 -1
- package/dist/question-list/question-list.api.js +0 -35
- package/dist/question-list/question-list.api.js.map +0 -1
- package/dist/question-list/question-list.interface.d.ts +0 -18
- package/dist/question-list/question-list.interface.d.ts.map +0 -1
- package/dist/question-list/question-list.interface.js +0 -5
- package/dist/question-list/question-list.interface.js.map +0 -1
- package/dist/repo/repo-context.utils.js +0 -81
- package/dist/repo/repo-context.utils.js.map +0 -1
- package/dist/repo/repo-manager.js +0 -156
- package/dist/repo/repo-manager.js.map +0 -1
- package/dist/repo/repo.api.js +0 -40
- package/dist/repo/repo.api.js.map +0 -1
- package/dist/repo/repo.interface.js +0 -8
- package/dist/repo/repo.interface.js.map +0 -1
- package/dist/repo/repo.script-loader.js +0 -108
- package/dist/repo/repo.script-loader.js.map +0 -1
- package/dist/review/review.api.d.ts +0 -14
- package/dist/review/review.api.d.ts.map +0 -1
- package/dist/review/review.api.js +0 -133
- package/dist/review/review.api.js.map +0 -1
- package/dist/review/review.interface.d.ts +0 -24
- package/dist/review/review.interface.d.ts.map +0 -1
- package/dist/review/review.interface.js +0 -10
- package/dist/review/review.interface.js.map +0 -1
- package/dist/review-v2/apis/post-review-setting.api.d.ts +0 -12
- package/dist/review-v2/apis/post-review-setting.api.d.ts.map +0 -1
- package/dist/review-v2/apis/post-review-setting.api.js +0 -27
- package/dist/review-v2/apis/post-review-setting.api.js.map +0 -1
- package/dist/review-v2/apis/post-review.api.d.ts +0 -13
- package/dist/review-v2/apis/post-review.api.d.ts.map +0 -1
- package/dist/review-v2/apis/post-review.api.js +0 -46
- package/dist/review-v2/apis/post-review.api.js.map +0 -1
- package/dist/review-v2/review-setting.interface.d.ts +0 -23
- package/dist/review-v2/review-setting.interface.d.ts.map +0 -1
- package/dist/review-v2/review-setting.interface.js +0 -5
- package/dist/review-v2/review-setting.interface.js.map +0 -1
- package/dist/review-v2/review.interface.d.ts +0 -20
- package/dist/review-v2/review.interface.d.ts.map +0 -1
- package/dist/review-v2/review.interface.js +0 -5
- package/dist/review-v2/review.interface.js.map +0 -1
- package/dist/service/api.interface.d.ts +0 -35
- package/dist/service/api.interface.d.ts.map +0 -1
- package/dist/service/api.interface.js +0 -12
- package/dist/service/api.interface.js.map +0 -1
- package/dist/service/base.interface.js +0 -7
- package/dist/service/base.interface.js.map +0 -1
- package/dist/service/service.interface.js +0 -11
- package/dist/service/service.interface.js.map +0 -1
- package/dist/shared/log/create-api-logger.d.ts +0 -17
- package/dist/shared/log/create-api-logger.d.ts.map +0 -1
- package/dist/shared/log/create-api-logger.js +0 -15
- package/dist/shared/log/create-api-logger.js.map +0 -1
- package/dist/shared/log/log-manager.js +0 -218
- package/dist/shared/log/log-manager.js.map +0 -1
- package/dist/shared/utils/config-path.utils.js +0 -85
- package/dist/shared/utils/config-path.utils.js.map +0 -1
- package/dist/shared/utils/error.utils.js +0 -15
- package/dist/shared/utils/error.utils.js.map +0 -1
- package/dist/shared/utils/id.utils.js +0 -5
- package/dist/shared/utils/id.utils.js.map +0 -1
- package/dist/supabase.js +0 -100
- package/dist/supabase.js.map +0 -1
- package/dist/task/local-task-registry.js +0 -153
- package/dist/task/local-task-registry.js.map +0 -1
- package/dist/task/task-manager.js +0 -217
- package/dist/task/task-manager.js.map +0 -1
- package/dist/task/task-repo-context.js +0 -12
- package/dist/task/task-repo-context.js.map +0 -1
- package/dist/task/task.api.js +0 -351
- package/dist/task/task.api.js.map +0 -1
- package/dist/task/task.interface.js +0 -36
- package/dist/task/task.interface.js.map +0 -1
- package/dist/task/task.utils.js +0 -2
- package/dist/task/task.utils.js.map +0 -1
- package/dist/word/word.api.js +0 -30
- package/dist/word/word.api.js.map +0 -1
- package/dist/word/word.interface.js +0 -6
- package/dist/word/word.interface.js.map +0 -1
- package/src/auth/auth.api.ts +0 -87
- package/src/feed/feed.interface.ts +0 -33
- package/src/file/file-manager.ts +0 -145
- package/src/file/file.api.ts +0 -43
- package/src/file/file.interface.ts +0 -30
- package/src/file-list/file-list.api.ts +0 -64
- package/src/file-list/file-list.interface.ts +0 -24
- package/src/node/node-manager.ts +0 -673
- package/src/node/node-task.preset.ts +0 -13
- package/src/question-list/question-list.api.ts +0 -42
- package/src/question-list/question-list.interface.ts +0 -21
- package/src/review/review.api.ts +0 -145
- package/src/review/review.interface.ts +0 -26
- package/src/review-v2/apis/post-review-setting.api.ts +0 -35
- package/src/review-v2/apis/post-review.api.ts +0 -59
- package/src/review-v2/review-setting.interface.ts +0 -26
- package/src/review-v2/review.interface.ts +0 -23
- package/src/service/api.interface.ts +0 -47
- package/src/shared/log/create-api-logger.ts +0 -25
package/src/task/task.api.ts
CHANGED
|
@@ -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 {
|
|
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.
|
|
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:
|
|
173
|
+
logger: LoggerWithScope,
|
|
182
174
|
action: TaskStatusAction | "patchTaskProgress" | "patchClaimTask",
|
|
183
175
|
task: Task,
|
|
184
|
-
|
|
176
|
+
data?: Record<string, unknown>,
|
|
185
177
|
): void {
|
|
186
|
-
logger.
|
|
187
|
-
topic:
|
|
188
|
-
|
|
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
|
-
...
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
351
|
+
const logger = createLogger({ module: "patchClaimTask", traceId, labels: { nodeId } });
|
|
358
352
|
|
|
353
|
+
let todoTask: Task;
|
|
359
354
|
try {
|
|
360
|
-
const { data:
|
|
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
|
-
|
|
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(
|
|
384
|
+
logTaskTransition(taskLogger, "patchClaimTask", data);
|
|
375
385
|
return generateResponse.success(data);
|
|
376
386
|
} catch (error) {
|
|
377
387
|
if (isOptimisticLockError(error)) {
|
|
378
|
-
|
|
379
|
-
|
|
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 =
|
|
382
|
-
|
|
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
|
-
});
|
|
@@ -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 };
|