monday-cli 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +675 -2
- package/README.md +223 -31
- package/dist/api/assets.d.ts +326 -0
- package/dist/api/assets.d.ts.map +1 -0
- package/dist/api/assets.js +519 -0
- package/dist/api/assets.js.map +1 -0
- package/dist/api/board-favorites.d.ts +329 -0
- package/dist/api/board-favorites.d.ts.map +1 -0
- package/dist/api/board-favorites.js +353 -0
- package/dist/api/board-favorites.js.map +1 -0
- package/dist/api/board-mutation-result.d.ts +9 -5
- package/dist/api/board-mutation-result.d.ts.map +1 -1
- package/dist/api/board-mutation-result.js +9 -5
- package/dist/api/board-mutation-result.js.map +1 -1
- package/dist/api/board-relation-validation.d.ts +161 -0
- package/dist/api/board-relation-validation.d.ts.map +1 -0
- package/dist/api/board-relation-validation.js +317 -0
- package/dist/api/board-relation-validation.js.map +1 -0
- package/dist/api/cache.d.ts +14 -5
- package/dist/api/cache.d.ts.map +1 -1
- package/dist/api/cache.js +8 -10
- package/dist/api/cache.js.map +1 -1
- package/dist/api/column-mapping.js +2 -2
- package/dist/api/column-mapping.js.map +1 -1
- package/dist/api/column-mutation-result.d.ts +9 -5
- package/dist/api/column-mutation-result.d.ts.map +1 -1
- package/dist/api/column-mutation-result.js +9 -5
- package/dist/api/column-mutation-result.js.map +1 -1
- package/dist/api/column-types.d.ts +37 -14
- package/dist/api/column-types.d.ts.map +1 -1
- package/dist/api/column-types.js +47 -6
- package/dist/api/column-types.js.map +1 -1
- package/dist/api/column-values.d.ts +234 -31
- package/dist/api/column-values.d.ts.map +1 -1
- package/dist/api/column-values.js +560 -124
- package/dist/api/column-values.js.map +1 -1
- package/dist/api/cross-board-search.d.ts +501 -0
- package/dist/api/cross-board-search.d.ts.map +1 -0
- package/dist/api/cross-board-search.js +547 -0
- package/dist/api/cross-board-search.js.map +1 -0
- package/dist/api/dev-conventions.d.ts +1038 -0
- package/dist/api/dev-conventions.d.ts.map +1 -0
- package/dist/api/dev-conventions.js +1556 -0
- package/dist/api/dev-conventions.js.map +1 -0
- package/dist/api/documents.d.ts +519 -0
- package/dist/api/documents.d.ts.map +1 -0
- package/dist/api/documents.js +586 -0
- package/dist/api/documents.js.map +1 -0
- package/dist/api/dry-run.d.ts +32 -5
- package/dist/api/dry-run.d.ts.map +1 -1
- package/dist/api/dry-run.js +149 -32
- package/dist/api/dry-run.js.map +1 -1
- package/dist/api/errors.d.ts.map +1 -1
- package/dist/api/errors.js +28 -7
- package/dist/api/errors.js.map +1 -1
- package/dist/api/group-mutation-result.d.ts +9 -5
- package/dist/api/group-mutation-result.d.ts.map +1 -1
- package/dist/api/group-mutation-result.js +9 -5
- package/dist/api/group-mutation-result.js.map +1 -1
- package/dist/api/item-history-projection.d.ts +919 -0
- package/dist/api/item-history-projection.d.ts.map +1 -0
- package/dist/api/item-history-projection.js +1104 -0
- package/dist/api/item-history-projection.js.map +1 -0
- package/dist/api/item-mutation-execute.d.ts +82 -0
- package/dist/api/item-mutation-execute.d.ts.map +1 -0
- package/dist/api/item-mutation-execute.js +199 -0
- package/dist/api/item-mutation-execute.js.map +1 -0
- package/dist/api/item-watch.d.ts +263 -0
- package/dist/api/item-watch.d.ts.map +1 -0
- package/dist/api/item-watch.js +709 -0
- package/dist/api/item-watch.js.map +1 -0
- package/dist/api/multipart-transport.d.ts +223 -0
- package/dist/api/multipart-transport.d.ts.map +1 -0
- package/dist/api/multipart-transport.js +274 -0
- package/dist/api/multipart-transport.js.map +1 -0
- package/dist/api/notifications.d.ts +156 -0
- package/dist/api/notifications.d.ts.map +1 -0
- package/dist/api/notifications.js +215 -0
- package/dist/api/notifications.js.map +1 -0
- package/dist/api/oauth-test-helper.d.ts +64 -0
- package/dist/api/oauth-test-helper.d.ts.map +1 -0
- package/dist/api/oauth-test-helper.js +179 -0
- package/dist/api/oauth-test-helper.js.map +1 -0
- package/dist/api/oauth.d.ts +198 -0
- package/dist/api/oauth.d.ts.map +1 -0
- package/dist/api/oauth.js +471 -0
- package/dist/api/oauth.js.map +1 -0
- package/dist/api/parallel-dispatch.d.ts +155 -0
- package/dist/api/parallel-dispatch.d.ts.map +1 -0
- package/dist/api/parallel-dispatch.js +243 -0
- package/dist/api/parallel-dispatch.js.map +1 -0
- package/dist/api/partial-success-bulk.d.ts +480 -0
- package/dist/api/partial-success-bulk.d.ts.map +1 -0
- package/dist/api/partial-success-bulk.js +436 -0
- package/dist/api/partial-success-bulk.js.map +1 -0
- package/dist/api/partial-success-mutation.d.ts +13 -1
- package/dist/api/partial-success-mutation.d.ts.map +1 -1
- package/dist/api/partial-success-mutation.js +5 -1
- package/dist/api/partial-success-mutation.js.map +1 -1
- package/dist/api/people.d.ts +54 -1
- package/dist/api/people.d.ts.map +1 -1
- package/dist/api/people.js +27 -3
- package/dist/api/people.js.map +1 -1
- package/dist/api/probes.d.ts +487 -0
- package/dist/api/probes.d.ts.map +1 -0
- package/dist/api/probes.js +881 -0
- package/dist/api/probes.js.map +1 -0
- package/dist/api/raw-document.d.ts.map +1 -1
- package/dist/api/raw-document.js +2 -2
- package/dist/api/raw-document.js.map +1 -1
- package/dist/api/raw-write.d.ts +12 -4
- package/dist/api/raw-write.d.ts.map +1 -1
- package/dist/api/raw-write.js +32 -14
- package/dist/api/raw-write.js.map +1 -1
- package/dist/api/resolution-context.d.ts +23 -11
- package/dist/api/resolution-context.d.ts.map +1 -1
- package/dist/api/resolution-context.js +53 -12
- package/dist/api/resolution-context.js.map +1 -1
- package/dist/api/resolution-pass.d.ts +30 -1
- package/dist/api/resolution-pass.d.ts.map +1 -1
- package/dist/api/resolution-pass.js +36 -1
- package/dist/api/resolution-pass.js.map +1 -1
- package/dist/api/resolve-client.d.ts +22 -0
- package/dist/api/resolve-client.d.ts.map +1 -1
- package/dist/api/resolve-client.js +9 -1
- package/dist/api/resolve-client.js.map +1 -1
- package/dist/api/response-root.d.ts +92 -46
- package/dist/api/response-root.d.ts.map +1 -1
- package/dist/api/response-root.js +93 -41
- package/dist/api/response-root.js.map +1 -1
- package/dist/api/tag-directory.d.ts +154 -0
- package/dist/api/tag-directory.d.ts.map +1 -0
- package/dist/api/tag-directory.js +325 -0
- package/dist/api/tag-directory.js.map +1 -0
- package/dist/api/time-tracking.d.ts +165 -0
- package/dist/api/time-tracking.d.ts.map +1 -0
- package/dist/api/time-tracking.js +135 -0
- package/dist/api/time-tracking.js.map +1 -0
- package/dist/api/transport.js +3 -3
- package/dist/api/transport.js.map +1 -1
- package/dist/api/usage.d.ts +190 -0
- package/dist/api/usage.d.ts.map +1 -0
- package/dist/api/usage.js +194 -0
- package/dist/api/usage.js.map +1 -0
- package/dist/api/users-fan-out-mutation.d.ts.map +1 -1
- package/dist/api/users-fan-out-mutation.js +10 -5
- package/dist/api/users-fan-out-mutation.js.map +1 -1
- package/dist/api/webhooks.d.ts +357 -0
- package/dist/api/webhooks.d.ts.map +1 -0
- package/dist/api/webhooks.js +333 -0
- package/dist/api/webhooks.js.map +1 -0
- package/dist/cli/envelope-out.d.ts +18 -1
- package/dist/cli/envelope-out.d.ts.map +1 -1
- package/dist/cli/envelope-out.js +16 -2
- package/dist/cli/envelope-out.js.map +1 -1
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +120 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/run.d.ts +32 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +3 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/commands/account/tags.d.ts +37 -0
- package/dist/commands/account/tags.d.ts.map +1 -0
- package/dist/commands/account/tags.js +84 -0
- package/dist/commands/account/tags.js.map +1 -0
- package/dist/commands/auth/login.d.ts +14 -0
- package/dist/commands/auth/login.d.ts.map +1 -0
- package/dist/commands/auth/login.js +314 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.d.ts +28 -0
- package/dist/commands/auth/logout.d.ts.map +1 -0
- package/dist/commands/auth/logout.js +94 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/board/archive.d.ts.map +1 -1
- package/dist/commands/board/archive.js +14 -14
- package/dist/commands/board/archive.js.map +1 -1
- package/dist/commands/board/column-create.d.ts +9 -8
- package/dist/commands/board/column-create.d.ts.map +1 -1
- package/dist/commands/board/column-create.js +61 -51
- package/dist/commands/board/column-create.js.map +1 -1
- package/dist/commands/board/column-delete.d.ts.map +1 -1
- package/dist/commands/board/column-delete.js +15 -16
- package/dist/commands/board/column-delete.js.map +1 -1
- package/dist/commands/board/column-update.d.ts.map +1 -1
- package/dist/commands/board/column-update.js +23 -22
- package/dist/commands/board/column-update.js.map +1 -1
- package/dist/commands/board/create.d.ts.map +1 -1
- package/dist/commands/board/create.js +14 -17
- package/dist/commands/board/create.js.map +1 -1
- package/dist/commands/board/delete.d.ts.map +1 -1
- package/dist/commands/board/delete.js +12 -15
- package/dist/commands/board/delete.js.map +1 -1
- package/dist/commands/board/describe.d.ts.map +1 -1
- package/dist/commands/board/describe.js +30 -0
- package/dist/commands/board/describe.js.map +1 -1
- package/dist/commands/board/duplicate.d.ts.map +1 -1
- package/dist/commands/board/duplicate.js +12 -13
- package/dist/commands/board/duplicate.js.map +1 -1
- package/dist/commands/board/favorites.d.ts +33 -0
- package/dist/commands/board/favorites.d.ts.map +1 -0
- package/dist/commands/board/favorites.js +74 -0
- package/dist/commands/board/favorites.js.map +1 -0
- package/dist/commands/board/find.d.ts +1 -1
- package/dist/commands/board/group-archive.d.ts.map +1 -1
- package/dist/commands/board/group-archive.js +12 -16
- package/dist/commands/board/group-archive.js.map +1 -1
- package/dist/commands/board/group-create.d.ts.map +1 -1
- package/dist/commands/board/group-create.js +9 -19
- package/dist/commands/board/group-create.js.map +1 -1
- package/dist/commands/board/group-delete.d.ts.map +1 -1
- package/dist/commands/board/group-delete.js +12 -16
- package/dist/commands/board/group-delete.js.map +1 -1
- package/dist/commands/board/group-duplicate.d.ts.map +1 -1
- package/dist/commands/board/group-duplicate.js +12 -16
- package/dist/commands/board/group-duplicate.js.map +1 -1
- package/dist/commands/board/group-update.d.ts.map +1 -1
- package/dist/commands/board/group-update.js +12 -11
- package/dist/commands/board/group-update.js.map +1 -1
- package/dist/commands/board/list.d.ts +1 -1
- package/dist/commands/board/update.d.ts.map +1 -1
- package/dist/commands/board/update.js +16 -11
- package/dist/commands/board/update.js.map +1 -1
- package/dist/commands/cache/list.d.ts +2 -0
- package/dist/commands/cache/list.d.ts.map +1 -1
- package/dist/commands/cache/list.js +2 -2
- package/dist/commands/cache/list.js.map +1 -1
- package/dist/commands/completion.d.ts +188 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +418 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/dev/_shared.d.ts +40 -0
- package/dist/commands/dev/_shared.d.ts.map +1 -0
- package/dist/commands/dev/_shared.js +104 -0
- package/dist/commands/dev/_shared.js.map +1 -0
- package/dist/commands/dev/configure.d.ts +36 -0
- package/dist/commands/dev/configure.d.ts.map +1 -0
- package/dist/commands/dev/configure.js +145 -0
- package/dist/commands/dev/configure.js.map +1 -0
- package/dist/commands/dev/discover.d.ts +34 -0
- package/dist/commands/dev/discover.d.ts.map +1 -0
- package/dist/commands/dev/discover.js +117 -0
- package/dist/commands/dev/discover.js.map +1 -0
- package/dist/commands/dev/doctor.d.ts +39 -0
- package/dist/commands/dev/doctor.d.ts.map +1 -0
- package/dist/commands/dev/doctor.js +91 -0
- package/dist/commands/dev/doctor.js.map +1 -0
- package/dist/commands/dev/epic/items.d.ts +24 -0
- package/dist/commands/dev/epic/items.d.ts.map +1 -0
- package/dist/commands/dev/epic/items.js +103 -0
- package/dist/commands/dev/epic/items.js.map +1 -0
- package/dist/commands/dev/epic/list.d.ts +36 -0
- package/dist/commands/dev/epic/list.d.ts.map +1 -0
- package/dist/commands/dev/epic/list.js +120 -0
- package/dist/commands/dev/epic/list.js.map +1 -0
- package/dist/commands/dev/release/list.d.ts +21 -0
- package/dist/commands/dev/release/list.d.ts.map +1 -0
- package/dist/commands/dev/release/list.js +73 -0
- package/dist/commands/dev/release/list.js.map +1 -0
- package/dist/commands/dev/sprint/current.d.ts +24 -0
- package/dist/commands/dev/sprint/current.d.ts.map +1 -0
- package/dist/commands/dev/sprint/current.js +90 -0
- package/dist/commands/dev/sprint/current.js.map +1 -0
- package/dist/commands/dev/sprint/items.d.ts +34 -0
- package/dist/commands/dev/sprint/items.d.ts.map +1 -0
- package/dist/commands/dev/sprint/items.js +118 -0
- package/dist/commands/dev/sprint/items.js.map +1 -0
- package/dist/commands/dev/sprint/list.d.ts +41 -0
- package/dist/commands/dev/sprint/list.d.ts.map +1 -0
- package/dist/commands/dev/sprint/list.js +104 -0
- package/dist/commands/dev/sprint/list.js.map +1 -0
- package/dist/commands/dev/task/block.d.ts +29 -0
- package/dist/commands/dev/task/block.d.ts.map +1 -0
- package/dist/commands/dev/task/block.js +106 -0
- package/dist/commands/dev/task/block.js.map +1 -0
- package/dist/commands/dev/task/done.d.ts +30 -0
- package/dist/commands/dev/task/done.d.ts.map +1 -0
- package/dist/commands/dev/task/done.js +113 -0
- package/dist/commands/dev/task/done.js.map +1 -0
- package/dist/commands/dev/task/list.d.ts +42 -0
- package/dist/commands/dev/task/list.d.ts.map +1 -0
- package/dist/commands/dev/task/list.js +227 -0
- package/dist/commands/dev/task/list.js.map +1 -0
- package/dist/commands/dev/task/start.d.ts +29 -0
- package/dist/commands/dev/task/start.d.ts.map +1 -0
- package/dist/commands/dev/task/start.js +90 -0
- package/dist/commands/dev/task/start.js.map +1 -0
- package/dist/commands/doc/get.d.ts +46 -0
- package/dist/commands/doc/get.d.ts.map +1 -0
- package/dist/commands/doc/get.js +95 -0
- package/dist/commands/doc/get.js.map +1 -0
- package/dist/commands/doc/list.d.ts +83 -0
- package/dist/commands/doc/list.d.ts.map +1 -0
- package/dist/commands/doc/list.js +248 -0
- package/dist/commands/doc/list.js.map +1 -0
- package/dist/commands/emit.d.ts.map +1 -1
- package/dist/commands/emit.js +5 -3
- package/dist/commands/emit.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +141 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/item/archive.d.ts.map +1 -1
- package/dist/commands/item/archive.js +11 -0
- package/dist/commands/item/archive.js.map +1 -1
- package/dist/commands/item/clear.d.ts.map +1 -1
- package/dist/commands/item/clear.js +15 -0
- package/dist/commands/item/clear.js.map +1 -1
- package/dist/commands/item/create.d.ts.map +1 -1
- package/dist/commands/item/create.js +41 -8
- package/dist/commands/item/create.js.map +1 -1
- package/dist/commands/item/delete.d.ts.map +1 -1
- package/dist/commands/item/delete.js +11 -0
- package/dist/commands/item/delete.js.map +1 -1
- package/dist/commands/item/duplicate.d.ts.map +1 -1
- package/dist/commands/item/duplicate.js +12 -0
- package/dist/commands/item/duplicate.js.map +1 -1
- package/dist/commands/item/history.d.ts +60 -0
- package/dist/commands/item/history.d.ts.map +1 -0
- package/dist/commands/item/history.js +309 -0
- package/dist/commands/item/history.js.map +1 -0
- package/dist/commands/item/list.d.ts.map +1 -1
- package/dist/commands/item/list.js +16 -13
- package/dist/commands/item/list.js.map +1 -1
- package/dist/commands/item/move.d.ts.map +1 -1
- package/dist/commands/item/move.js +41 -7
- package/dist/commands/item/move.js.map +1 -1
- package/dist/commands/item/search.d.ts +99 -15
- package/dist/commands/item/search.d.ts.map +1 -1
- package/dist/commands/item/search.js +480 -36
- package/dist/commands/item/search.js.map +1 -1
- package/dist/commands/item/set.d.ts.map +1 -1
- package/dist/commands/item/set.js +52 -8
- package/dist/commands/item/set.js.map +1 -1
- package/dist/commands/item/time-track/start.d.ts +61 -0
- package/dist/commands/item/time-track/start.d.ts.map +1 -0
- package/dist/commands/item/time-track/start.js +138 -0
- package/dist/commands/item/time-track/start.js.map +1 -0
- package/dist/commands/item/time-track/stop.d.ts +32 -0
- package/dist/commands/item/time-track/stop.d.ts.map +1 -0
- package/dist/commands/item/time-track/stop.js +97 -0
- package/dist/commands/item/time-track/stop.js.map +1 -0
- package/dist/commands/item/update.d.ts +2 -0
- package/dist/commands/item/update.d.ts.map +1 -1
- package/dist/commands/item/update.js +164 -113
- package/dist/commands/item/update.js.map +1 -1
- package/dist/commands/item/upload.d.ts +108 -0
- package/dist/commands/item/upload.d.ts.map +1 -0
- package/dist/commands/item/upload.js +370 -0
- package/dist/commands/item/upload.js.map +1 -0
- package/dist/commands/item/upsert.d.ts.map +1 -1
- package/dist/commands/item/upsert.js +48 -1
- package/dist/commands/item/upsert.js.map +1 -1
- package/dist/commands/item/watch.d.ts +90 -0
- package/dist/commands/item/watch.d.ts.map +1 -0
- package/dist/commands/item/watch.js +342 -0
- package/dist/commands/item/watch.js.map +1 -0
- package/dist/commands/notification/send.d.ts +60 -0
- package/dist/commands/notification/send.d.ts.map +1 -0
- package/dist/commands/notification/send.js +147 -0
- package/dist/commands/notification/send.js.map +1 -0
- package/dist/commands/parse-argv.d.ts.map +1 -1
- package/dist/commands/parse-argv.js +14 -4
- package/dist/commands/parse-argv.js.map +1 -1
- package/dist/commands/raw/index.d.ts.map +1 -1
- package/dist/commands/raw/index.js +13 -15
- package/dist/commands/raw/index.js.map +1 -1
- package/dist/commands/run-by-id-lookup.d.ts.map +1 -1
- package/dist/commands/run-by-id-lookup.js +2 -2
- package/dist/commands/run-by-id-lookup.js.map +1 -1
- package/dist/commands/schema/index.d.ts +2 -0
- package/dist/commands/schema/index.d.ts.map +1 -1
- package/dist/commands/status.d.ts +120 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +365 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update/body-source.d.ts.map +1 -1
- package/dist/commands/update/body-source.js +2 -2
- package/dist/commands/update/body-source.js.map +1 -1
- package/dist/commands/update/create.d.ts +2 -3
- package/dist/commands/update/create.d.ts.map +1 -1
- package/dist/commands/update/create.js +15 -3
- package/dist/commands/update/create.js.map +1 -1
- package/dist/commands/update/delete.d.ts.map +1 -1
- package/dist/commands/update/delete.js +11 -0
- package/dist/commands/update/delete.js.map +1 -1
- package/dist/commands/update/edit.d.ts.map +1 -1
- package/dist/commands/update/edit.js +11 -0
- package/dist/commands/update/edit.js.map +1 -1
- package/dist/commands/update/list.d.ts.map +1 -1
- package/dist/commands/update/list.js +15 -12
- package/dist/commands/update/list.js.map +1 -1
- package/dist/commands/update/reply.d.ts.map +1 -1
- package/dist/commands/update/reply.js +11 -0
- package/dist/commands/update/reply.js.map +1 -1
- package/dist/commands/update/toggle.d.ts.map +1 -1
- package/dist/commands/update/toggle.js +13 -0
- package/dist/commands/update/toggle.js.map +1 -1
- package/dist/commands/update/upload.d.ts +69 -0
- package/dist/commands/update/upload.d.ts.map +1 -0
- package/dist/commands/update/upload.js +235 -0
- package/dist/commands/update/upload.js.map +1 -0
- package/dist/commands/usage.d.ts +58 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +94 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/webhook/create.d.ts +74 -0
- package/dist/commands/webhook/create.d.ts.map +1 -0
- package/dist/commands/webhook/create.js +150 -0
- package/dist/commands/webhook/create.js.map +1 -0
- package/dist/commands/webhook/delete.d.ts +46 -0
- package/dist/commands/webhook/delete.d.ts.map +1 -0
- package/dist/commands/webhook/delete.js +141 -0
- package/dist/commands/webhook/delete.js.map +1 -0
- package/dist/commands/webhook/list.d.ts +23 -0
- package/dist/commands/webhook/list.d.ts.map +1 -0
- package/dist/commands/webhook/list.js +68 -0
- package/dist/commands/webhook/list.js.map +1 -0
- package/dist/commands/workspace/create.d.ts.map +1 -1
- package/dist/commands/workspace/create.js +16 -0
- package/dist/commands/workspace/create.js.map +1 -1
- package/dist/commands/workspace/delete.d.ts.map +1 -1
- package/dist/commands/workspace/delete.js +13 -13
- package/dist/commands/workspace/delete.js.map +1 -1
- package/dist/commands/workspace/list.d.ts +1 -1
- package/dist/commands/workspace/update.d.ts.map +1 -1
- package/dist/commands/workspace/update.js +15 -15
- package/dist/commands/workspace/update.js.map +1 -1
- package/dist/config/credentials.d.ts +189 -0
- package/dist/config/credentials.d.ts.map +1 -0
- package/dist/config/credentials.js +300 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/profiles.d.ts +125 -0
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/config/profiles.js +227 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/types/global-flags.d.ts +1 -1
- package/dist/types/global-flags.d.ts.map +1 -1
- package/dist/types/global-flags.js +28 -16
- package/dist/types/global-flags.js.map +1 -1
- package/dist/types/ids.d.ts +4 -0
- package/dist/types/ids.d.ts.map +1 -1
- package/dist/types/ids.js +12 -3
- package/dist/types/ids.js.map +1 -1
- package/dist/utils/errors.d.ts +57 -3
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +69 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/fs.d.ts +35 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +36 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/json.d.ts +60 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +86 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/mime.d.ts +24 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +64 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/output/envelope.d.ts +30 -0
- package/dist/utils/output/envelope.d.ts.map +1 -1
- package/dist/utils/output/envelope.js +26 -0
- package/dist/utils/output/envelope.js.map +1 -1
- package/dist/utils/output/ndjson.d.ts +90 -3
- package/dist/utils/output/ndjson.d.ts.map +1 -1
- package/dist/utils/output/ndjson.js +33 -0
- package/dist/utils/output/ndjson.js.map +1 -1
- package/dist/utils/redact.d.ts.map +1 -1
- package/dist/utils/redact.js +31 -0
- package/dist/utils/redact.js.map +1 -1
- package/dist/utils/signal.d.ts +42 -0
- package/dist/utils/signal.d.ts.map +1 -0
- package/dist/utils/signal.js +45 -0
- package/dist/utils/signal.js.map +1 -0
- package/package.json +2 -1
- package/dist/commands/account/client-helper.d.ts +0 -37
- package/dist/commands/account/client-helper.d.ts.map +0 -1
- package/dist/commands/account/client-helper.js +0 -55
- package/dist/commands/account/client-helper.js.map +0 -1
|
@@ -0,0 +1,1104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-item activity-log + comment-thread projection for the v0.3-M24
|
|
3
|
+
* `monday item history <iid>` verb (`cli-design.md` §13 v0.3 entry).
|
|
4
|
+
*
|
|
5
|
+
* **What `monday item history` answers:** "show me every change +
|
|
6
|
+
* comment on this item, chronologically, in one stream" — without
|
|
7
|
+
* the agent walking `activity_logs` AND `updates` separately and
|
|
8
|
+
* folding by `created_at` by hand. Two Monday surfaces feed the
|
|
9
|
+
* stream:
|
|
10
|
+
*
|
|
11
|
+
* 1. `boards(ids:) { activity_logs(item_ids:, from:, to:,
|
|
12
|
+
* page:, limit:) }` — Monday's per-board activity log,
|
|
13
|
+
* filtered to the target item via `item_ids` AND additionally
|
|
14
|
+
* filtered WALKER-SIDE (post-fetch, before projection) to
|
|
15
|
+
* `entity = 'pulse'` (the `item_ids` arg ALONE does NOT
|
|
16
|
+
* exclude board-scoped events; empirical-probe finding
|
|
17
|
+
* 2026-05-11). Page-numbered pagination (Monday's native
|
|
18
|
+
* shape; `--activity-logs-page <n>` / `--limit <n>` flags
|
|
19
|
+
* surface it).
|
|
20
|
+
* 2. `items(ids:) { updates(limit:, page:) { ... replies { ...
|
|
21
|
+
* } } }` — Monday's comment thread (top-level updates +
|
|
22
|
+
* nested replies). Projected into synthesized
|
|
23
|
+
* `update_posted` + `update_replied` event-objects so the
|
|
24
|
+
* merged stream is uniform.
|
|
25
|
+
*
|
|
26
|
+
* The merge projector orders the unified stream by `created_at`
|
|
27
|
+
* ascending; ties break by `id` for deterministic output across
|
|
28
|
+
* runs.
|
|
29
|
+
*
|
|
30
|
+
* **Decision 2 closure** (`a1f3025`, M24-prep empirical probe pass
|
|
31
|
+
* 2026-05-11; full findings at v0.3-plan §8 Decision 2 closure).
|
|
32
|
+
* Three load-bearing findings from the live probe against a real
|
|
33
|
+
* workspace + 19 captured `activity_logs` rows on a production
|
|
34
|
+
* board:
|
|
35
|
+
*
|
|
36
|
+
* - **Schema field name is `event`, NOT `kind`.** Monday's
|
|
37
|
+
* `ActivityLogType` exposes 7 fields per the introspection
|
|
38
|
+
* probe (all NON_NULL String): `account_id`, `created_at`,
|
|
39
|
+
* `data`, `entity`, `event`, `id`, `user_id`. The v0.3-plan
|
|
40
|
+
* §3 M24 description used "kind" as the synonym; the projector
|
|
41
|
+
* keeps `kind` as the CLI agent-facing discriminator (domain-
|
|
42
|
+
* neutral) but maps it 1:1 from the wire's `event` slot.
|
|
43
|
+
* - **Observed event taxonomy (production data; 19 rows on one
|
|
44
|
+
* board over 30 days; NOT exhaustive):** `create_column`
|
|
45
|
+
* (10×), `update_column_value` (4×; the dominant ITEM-SCOPED
|
|
46
|
+
* event), `create_group` (2×), `board_workspace_id_changed`
|
|
47
|
+
* (1×), `update_board_name` (1×), `update_board_nickname`
|
|
48
|
+
* (1×). The `update_column_value` payload carries `column_id`
|
|
49
|
+
* + `column_type` + `value` + `previous_value` + `textual_value`
|
|
50
|
+
* + `pulse_id` + `pulse_name`; `previous_value` is sometimes
|
|
51
|
+
* `{}` for first-set events (decoded defensively as
|
|
52
|
+
* "previously-unset" — preserved as `{}` on the projected
|
|
53
|
+
* event so agents distinguish "first set" from "no prior
|
|
54
|
+
* value tracked"). The runtime projector applies one level
|
|
55
|
+
* of nested-JSON unwrap on `value` / `previous_value` so the
|
|
56
|
+
* before/after slots carry structured payloads (e.g.
|
|
57
|
+
* `{label, index}` for status, ISO string for date) rather
|
|
58
|
+
* than opaque JSON-string scalars.
|
|
59
|
+
* - **`entity` field discriminates item-scoped from board-scoped
|
|
60
|
+
* events.** Observed values: `pulse` (4×; item-scoped) and
|
|
61
|
+
* `board` (15×; board-scoped). The walker filters
|
|
62
|
+
* `entity = 'pulse'` to drop board-level noise (column
|
|
63
|
+
* additions, group creation, board renames) that aren't part
|
|
64
|
+
* of the item's history. **The `item_ids` filter alone is
|
|
65
|
+
* INSUFFICIENT** — passing it does NOT exclude board-scoped
|
|
66
|
+
* events from the response.
|
|
67
|
+
*
|
|
68
|
+
* **Eventual-consistency caveat (carry to cli-design §13 v0.3
|
|
69
|
+
* entry).** Monday's `activity_logs` has an empirically-measured
|
|
70
|
+
* propagation lag **>30s** on freshly-edited boards. The verb's
|
|
71
|
+
* help text MUST NOT promise immediate-history for newly-modified
|
|
72
|
+
* items; agents polling `monday item history` after a write should
|
|
73
|
+
* wait at least 30s before expecting their write to surface.
|
|
74
|
+
*
|
|
75
|
+
* **Update + Reply shapes (also pinned by the probe).** `Update`
|
|
76
|
+
* carries 16 fields per introspection; the projector projects only
|
|
77
|
+
* the load-bearing ones: `id` (NON_NULL ID), `body` (NON_NULL
|
|
78
|
+
* String), `text_body` (nullable String), `created_at` (nullable
|
|
79
|
+
* `Date`), `creator_id` (nullable String), `replies` (LIST[Reply!]
|
|
80
|
+
* with the list itself nullable; items non-null). `Reply` carries
|
|
81
|
+
* its OWN `kind: String!` field — separate taxonomy from
|
|
82
|
+
* `activity_logs.event` — and the projector surfaces it under the
|
|
83
|
+
* synthesized `update_replied` event's `reply_kind` slot.
|
|
84
|
+
*
|
|
85
|
+
* **Runtime composition.** {@link fetchItemHistory} drives the
|
|
86
|
+
* two-source walker; {@link projectActivityLogRow},
|
|
87
|
+
* {@link projectUpdateRow}, and {@link projectReplyRow} are the
|
|
88
|
+
* per-row projectors (the activity-log projector reads the wire
|
|
89
|
+
* `data` JSON, dispatches on `event`, and applies a one-level
|
|
90
|
+
* nested-JSON unwrap on `update_column_value`'s `value` /
|
|
91
|
+
* `previous_value` so agents see the structured payload — e.g.
|
|
92
|
+
* `{label, index}` for status, ISO string for date — rather than
|
|
93
|
+
* an opaque JSON-string). The walker filters
|
|
94
|
+
* `entity === ITEM_SCOPED_ENTITY` walker-side (single source of
|
|
95
|
+
* truth per Decision 2 closure; projector does NOT re-filter).
|
|
96
|
+
*
|
|
97
|
+
* **Streaming reuse.** Per the v0.3-plan §3 M24 deliverable, the
|
|
98
|
+
* verb reuses `startNdjsonStream` (R52) when `--stream` is on; the
|
|
99
|
+
* trailer meta carries `{has_more, total_returned, complexity,
|
|
100
|
+
* source}` per cli-design §6.3 + the symmetric page-numbered
|
|
101
|
+
* per-source `activity_logs.last_page` + `updates.last_page` slots
|
|
102
|
+
* (both 1-indexed; `null` when the walker exhausted that source) so
|
|
103
|
+
* agents resuming a partial walk re-issue with the per-source
|
|
104
|
+
* `last_page + 1`. No cursor surface at v0.3 — both sources
|
|
105
|
+
* paginate page-numbered.
|
|
106
|
+
*/
|
|
107
|
+
import { z } from 'zod';
|
|
108
|
+
import { isPlainObject } from '../utils/json.js';
|
|
109
|
+
import { unwrapOrThrow } from '../utils/parse-boundary.js';
|
|
110
|
+
/**
|
|
111
|
+
* Wire field name on `ActivityLogType` that discriminates
|
|
112
|
+
* item-scoped (`pulse`) from board-scoped (`board`) events per the
|
|
113
|
+
* Decision 2 closure entity-filter finding. The walker filters on
|
|
114
|
+
* this constant before handing rows to the projector; the projector
|
|
115
|
+
* itself does NOT re-filter (single source of truth at the walker
|
|
116
|
+
* layer).
|
|
117
|
+
*/
|
|
118
|
+
export const ITEM_SCOPED_ENTITY = 'pulse';
|
|
119
|
+
/**
|
|
120
|
+
* Default per-page slice for `activity_logs(limit: <n>, page: <n>)`.
|
|
121
|
+
* Monday's `activity_logs` resolver caps the per-call slice at 10000;
|
|
122
|
+
* the CLI default of 100 keeps the per-call latency below the per-
|
|
123
|
+
* page budget while letting `--limit <n>` cap the aggregate. Mirrors
|
|
124
|
+
* the v0.1 `DEFAULT_PAGE_SIZE` of 100.
|
|
125
|
+
*/
|
|
126
|
+
export const DEFAULT_HISTORY_PAGE_SIZE = 100;
|
|
127
|
+
/**
|
|
128
|
+
* Hard cap on `--limit` for `activity_logs` per-call slice. Monday's
|
|
129
|
+
* documented ceiling is 10000; the CLI mirrors it so the parse
|
|
130
|
+
* boundary rejects over-large requests with `usage_error` rather
|
|
131
|
+
* than letting Monday's server-side rejection surface as
|
|
132
|
+
* `validation_failed` mid-walk.
|
|
133
|
+
*/
|
|
134
|
+
export const HARD_CAP_HISTORY_PAGE_SIZE = 10_000;
|
|
135
|
+
/**
|
|
136
|
+
* Stage-1 GraphQL document — `activity_logs` per-page slice.
|
|
137
|
+
*
|
|
138
|
+
* Per the Decision 2 closure introspection finding,
|
|
139
|
+
* `ActivityLogType` has 7 NON_NULL String fields. The projector
|
|
140
|
+
* reads all 6 non-`account_id` slots (`account_id` carries no
|
|
141
|
+
* item-history signal — every row in a single-account CLI session
|
|
142
|
+
* shares it).
|
|
143
|
+
*
|
|
144
|
+
* **`item_ids` filter is necessary BUT NOT SUFFICIENT.** Per the
|
|
145
|
+
* probe finding, board-scoped events (entity = 'board') leak
|
|
146
|
+
* through even with `item_ids` set. The WALKER
|
|
147
|
+
* ({@link fetchItemHistory}) filters `row.entity ===
|
|
148
|
+
* ITEM_SCOPED_ENTITY` immediately after the page parses and
|
|
149
|
+
* BEFORE handing rows to {@link projectActivityLogRow}. The
|
|
150
|
+
* projector itself does NOT re-filter — single source of truth at
|
|
151
|
+
* the walker layer per Decision 2 closure. Server-side filtering
|
|
152
|
+
* would require a custom GraphQL middleware Monday doesn't expose;
|
|
153
|
+
* filtering later than the walker would force row-shaping code to
|
|
154
|
+
* know about the entity discriminator, which belongs to the
|
|
155
|
+
* walker's "which rows are part of THIS item's history" question,
|
|
156
|
+
* not the projector's "how do I shape this row's payload" question.
|
|
157
|
+
*
|
|
158
|
+
* Monday's `activity_logs(item_ids:, from:, to:, page:, limit:)`
|
|
159
|
+
* signature accepts ISO-8601 timestamps for `from` / `to` per the
|
|
160
|
+
* sibling `created_at` ISO8601DateTime scalar; nullable on both
|
|
161
|
+
* sides so a partial range (`--since` only / `--until` only) maps
|
|
162
|
+
* cleanly to omitting the absent slot.
|
|
163
|
+
*/
|
|
164
|
+
export const ACTIVITY_LOGS_QUERY = `
|
|
165
|
+
query ItemHistoryActivityLogs(
|
|
166
|
+
$bid: [ID!]!,
|
|
167
|
+
$iid: [ID!]!,
|
|
168
|
+
$from: ISO8601DateTime,
|
|
169
|
+
$to: ISO8601DateTime,
|
|
170
|
+
$page: Int!,
|
|
171
|
+
$limit: Int!
|
|
172
|
+
) {
|
|
173
|
+
boards(ids: $bid) {
|
|
174
|
+
id
|
|
175
|
+
activity_logs(
|
|
176
|
+
item_ids: $iid,
|
|
177
|
+
from: $from,
|
|
178
|
+
to: $to,
|
|
179
|
+
page: $page,
|
|
180
|
+
limit: $limit
|
|
181
|
+
) {
|
|
182
|
+
id
|
|
183
|
+
event
|
|
184
|
+
entity
|
|
185
|
+
user_id
|
|
186
|
+
created_at
|
|
187
|
+
data
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
`;
|
|
192
|
+
/**
|
|
193
|
+
* Stage-2 GraphQL document — `items(ids:) { updates(...) }` for
|
|
194
|
+
* the comment-thread source.
|
|
195
|
+
*
|
|
196
|
+
* Per the Decision 2 closure introspection finding, `Update` has
|
|
197
|
+
* 16 fields; the projector selects only the load-bearing slots
|
|
198
|
+
* (id / body / text_body / created_at / creator_id / replies +
|
|
199
|
+
* the Reply sub-selection). Other fields (`likes`, `pinned_to_top`,
|
|
200
|
+
* `viewers`, `assets`) are not part of the item-history surface in
|
|
201
|
+
* v0.3; a v0.4 follow-up may extend the projection under the
|
|
202
|
+
* `update_posted` event's `after` slot if those fields become
|
|
203
|
+
* agent-useful (envelope-additive per §6.1).
|
|
204
|
+
*
|
|
205
|
+
* **Update.created_at + Reply.created_at are nullable** per the
|
|
206
|
+
* probe introspection (both fields are `SCALAR/Date`, nullable).
|
|
207
|
+
* The projector substitutes `Update.edited_at` (NON_NULL Date) as
|
|
208
|
+
* the chronological key when `created_at` is null — silent
|
|
209
|
+
* projection behaviour (NOT a warning surface; the substitution is
|
|
210
|
+
* deterministic + agents observing a null-`created_at` Update on
|
|
211
|
+
* the wire reproduce the same merge order on a re-walk). v0.3's
|
|
212
|
+
* `warnings[]` shape is `unknown_event_kind` only; adding a
|
|
213
|
+
* `synthesized_created_at` warning is a v0.4 envelope-additive
|
|
214
|
+
* extension if the substitution turns out to be agent-visible in
|
|
215
|
+
* practice.
|
|
216
|
+
*
|
|
217
|
+
* Monday's `updates(limit:, page:)` signature is page-numbered;
|
|
218
|
+
* the projector exposes `--updates-page <n>` so the two sources
|
|
219
|
+
* paginate independently (activity_logs and updates have their own
|
|
220
|
+
* page counters; merging them onto a single `--page <n>` flag would
|
|
221
|
+
* conflate two different denominators).
|
|
222
|
+
*/
|
|
223
|
+
export const UPDATES_QUERY = `
|
|
224
|
+
query ItemHistoryUpdates(
|
|
225
|
+
$iid: [ID!]!,
|
|
226
|
+
$page: Int!,
|
|
227
|
+
$limit: Int!
|
|
228
|
+
) {
|
|
229
|
+
items(ids: $iid) {
|
|
230
|
+
id
|
|
231
|
+
updates(limit: $limit, page: $page) {
|
|
232
|
+
id
|
|
233
|
+
body
|
|
234
|
+
text_body
|
|
235
|
+
created_at
|
|
236
|
+
edited_at
|
|
237
|
+
creator_id
|
|
238
|
+
replies {
|
|
239
|
+
id
|
|
240
|
+
kind
|
|
241
|
+
body
|
|
242
|
+
text_body
|
|
243
|
+
created_at
|
|
244
|
+
updated_at
|
|
245
|
+
creator_id
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
`;
|
|
251
|
+
/**
|
|
252
|
+
* Wire-shape schema for an `ActivityLogType` row (Decision 2 closure
|
|
253
|
+
* introspection finding — 7 NON_NULL String fields). `.loose()` so
|
|
254
|
+
* future Monday surface extensions don't break the parse — the
|
|
255
|
+
* projector reads only the fields it knows about and forward-compat
|
|
256
|
+
* fields pass through to no consumer.
|
|
257
|
+
*/
|
|
258
|
+
export const rawActivityLogRowSchema = z
|
|
259
|
+
.object({
|
|
260
|
+
id: z.string().min(1),
|
|
261
|
+
event: z.string().min(1),
|
|
262
|
+
entity: z.string().min(1),
|
|
263
|
+
user_id: z.string().min(1),
|
|
264
|
+
created_at: z.string().min(1),
|
|
265
|
+
data: z.string(),
|
|
266
|
+
})
|
|
267
|
+
.loose();
|
|
268
|
+
/**
|
|
269
|
+
* Wire-shape schema for one `Reply` row inside `Update.replies`.
|
|
270
|
+
* Per the Decision 2 closure introspection finding, `Reply.id` +
|
|
271
|
+
* `Reply.body` + `Reply.kind` are NON_NULL; `Reply.created_at` is
|
|
272
|
+
* nullable Date; `Reply.creator_id` is nullable String.
|
|
273
|
+
*
|
|
274
|
+
* **`Reply.kind` is a separate taxonomy from
|
|
275
|
+
* `activity_logs.event`.** Reply's kind discriminates comment-thread
|
|
276
|
+
* reply types (e.g., a regular reply vs a system-generated reply);
|
|
277
|
+
* activity_logs's event discriminates board-level change types. The
|
|
278
|
+
* projector surfaces `Reply.kind` under the synthesized
|
|
279
|
+
* `update_replied` event's `reply_kind` slot so agents can
|
|
280
|
+
* introspect it without confusion.
|
|
281
|
+
*/
|
|
282
|
+
export const rawReplyRowSchema = z
|
|
283
|
+
.object({
|
|
284
|
+
id: z.string().min(1),
|
|
285
|
+
body: z.string(),
|
|
286
|
+
kind: z.string().min(1),
|
|
287
|
+
text_body: z.string().nullable(),
|
|
288
|
+
created_at: z.string().nullable(),
|
|
289
|
+
updated_at: z.string().nullable(),
|
|
290
|
+
creator_id: z.string().nullable(),
|
|
291
|
+
})
|
|
292
|
+
.loose();
|
|
293
|
+
/**
|
|
294
|
+
* Wire-shape schema for one `Update` row. `created_at` is nullable
|
|
295
|
+
* per the probe introspection (Date scalar, optional); the
|
|
296
|
+
* projector substitutes `edited_at` (NON_NULL Date) when
|
|
297
|
+
* `created_at` is absent.
|
|
298
|
+
*/
|
|
299
|
+
export const rawUpdateRowSchema = z
|
|
300
|
+
.object({
|
|
301
|
+
id: z.string().min(1),
|
|
302
|
+
body: z.string(),
|
|
303
|
+
text_body: z.string().nullable(),
|
|
304
|
+
created_at: z.string().nullable(),
|
|
305
|
+
edited_at: z.string().min(1),
|
|
306
|
+
creator_id: z.string().nullable(),
|
|
307
|
+
replies: z.array(rawReplyRowSchema).nullable(),
|
|
308
|
+
})
|
|
309
|
+
.loose();
|
|
310
|
+
/**
|
|
311
|
+
* Common base-field shape on every projected `HistoryEvent` variant.
|
|
312
|
+
*
|
|
313
|
+
* - `id` — stable per-row identifier. Activity-log rows reuse the
|
|
314
|
+
* wire `ActivityLogType.id`; `update_posted` reuses
|
|
315
|
+
* `Update.id`; `update_replied` reuses `Reply.id`. Cross-source
|
|
316
|
+
* `id` clashes are not possible — Monday assigns separate ID
|
|
317
|
+
* spaces to activity_logs / updates / replies.
|
|
318
|
+
* - `created_at` — ISO-8601 timestamp. The chronological merge key
|
|
319
|
+
* (see `mergeByCreatedAt`).
|
|
320
|
+
* - `actor_id` — nullable to accommodate the wire variance:
|
|
321
|
+
* `ActivityLogType.user_id` is NON_NULL per the probe;
|
|
322
|
+
* `Update.creator_id` is nullable; `Reply.creator_id` is
|
|
323
|
+
* nullable. `null` means "no actor recorded" (system event,
|
|
324
|
+
* deleted user); agents distinguish via the variant `kind`.
|
|
325
|
+
*/
|
|
326
|
+
const baseEventFields = {
|
|
327
|
+
id: z.string().min(1),
|
|
328
|
+
created_at: z.string().min(1),
|
|
329
|
+
actor_id: z.string().nullable(),
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* **`update_column_value`** — the dominant ITEM-SCOPED activity-log
|
|
333
|
+
* event per the Decision 2 closure observed-events list (4× of 19
|
|
334
|
+
* rows; the only item-scoped kind in the sample). Carries the
|
|
335
|
+
* column-edit before / after payload.
|
|
336
|
+
*
|
|
337
|
+
* Schema slots:
|
|
338
|
+
* - `column_id` + `column_type` from the wire `data` payload
|
|
339
|
+
* (always present per the probe).
|
|
340
|
+
* - `before` + `after` as `z.unknown()` slots carrying the
|
|
341
|
+
* parsed `previous_value` / `value` JSON. The runtime
|
|
342
|
+
* projector applies one level of nested-JSON unwrap so
|
|
343
|
+
* agents see structured payloads (e.g. `{label, index}` for
|
|
344
|
+
* status, ISO string for date) rather than opaque JSON-
|
|
345
|
+
* string scalars. `z.unknown()` keeps the schema permissive
|
|
346
|
+
* so future Monday column types don't break the parse —
|
|
347
|
+
* agents introspect via `column_type` and the runtime
|
|
348
|
+
* payload.
|
|
349
|
+
* - `textual_value` — Monday's human-readable rendering of the
|
|
350
|
+
* new value (always present per the probe; nullable for
|
|
351
|
+
* defensive forward-compat with future column types Monday
|
|
352
|
+
* may not provide a textual rendering for).
|
|
353
|
+
* - `pulse_id` + `pulse_name` — item identity for cross-board
|
|
354
|
+
* consumers; nullable for subitem variants where the parent
|
|
355
|
+
* identification carries the load. `pulse_id` ships as an
|
|
356
|
+
* unquoted JSON number on the wire (probe-confirmed); the
|
|
357
|
+
* runtime projector stringifies it via
|
|
358
|
+
* `readNullableIdField` (Codex impl round-2 P2-1).
|
|
359
|
+
*/
|
|
360
|
+
export const updateColumnValueEventSchema = z
|
|
361
|
+
.object({
|
|
362
|
+
...baseEventFields,
|
|
363
|
+
kind: z.literal('update_column_value'),
|
|
364
|
+
column_id: z.string().min(1),
|
|
365
|
+
column_type: z.string().min(1),
|
|
366
|
+
before: z.unknown(),
|
|
367
|
+
after: z.unknown(),
|
|
368
|
+
textual_value: z.string().nullable(),
|
|
369
|
+
pulse_id: z.string().nullable(),
|
|
370
|
+
pulse_name: z.string().nullable(),
|
|
371
|
+
})
|
|
372
|
+
.strict();
|
|
373
|
+
/**
|
|
374
|
+
* Board-scoped activity-log variants. The walker filters
|
|
375
|
+
* `entity = 'pulse'` BEFORE handing rows to the projector, so these
|
|
376
|
+
* variants are not surfaced on the projected stream in normal
|
|
377
|
+
* operation. They stay in the discriminated union as parser-
|
|
378
|
+
* roundtrip targets so a future regression that bypasses the
|
|
379
|
+
* entity filter falls back to the typed variant rather than to
|
|
380
|
+
* `unknown` (cleaner failure mode; agents see the expected kind
|
|
381
|
+
* literal rather than a fallback shape).
|
|
382
|
+
*
|
|
383
|
+
* Both `before` / `after` carry the raw parsed JSON payload as
|
|
384
|
+
* `z.unknown()` slots. Uniform shape (not `null` even for
|
|
385
|
+
* creation-shaped events) because the observed taxonomy includes
|
|
386
|
+
* both creation events (`create_column`, `create_group`) where
|
|
387
|
+
* `before` is meaningless AND edit events (`update_board_name`,
|
|
388
|
+
* `update_board_nickname`, `board_workspace_id_changed`) where
|
|
389
|
+
* `before` carries the prior value from the wire `data.previous_value`
|
|
390
|
+
* payload — uniform `z.unknown()` keeps the discriminator schema
|
|
391
|
+
* stable regardless of which variant a row resolves to.
|
|
392
|
+
*/
|
|
393
|
+
const boardScopedEventSchema = (kindLiteral) => z
|
|
394
|
+
.object({
|
|
395
|
+
...baseEventFields,
|
|
396
|
+
kind: z.literal(kindLiteral),
|
|
397
|
+
before: z.unknown(),
|
|
398
|
+
after: z.unknown(),
|
|
399
|
+
})
|
|
400
|
+
.strict();
|
|
401
|
+
export const createColumnEventSchema = boardScopedEventSchema('create_column');
|
|
402
|
+
export const createGroupEventSchema = boardScopedEventSchema('create_group');
|
|
403
|
+
export const updateBoardNameEventSchema = boardScopedEventSchema('update_board_name');
|
|
404
|
+
export const updateBoardNicknameEventSchema = boardScopedEventSchema('update_board_nickname');
|
|
405
|
+
export const boardWorkspaceIdChangedEventSchema = boardScopedEventSchema('board_workspace_id_changed');
|
|
406
|
+
/**
|
|
407
|
+
* **`update_posted`** — synthesized event for a top-level comment
|
|
408
|
+
* on the item. The projector maps `Update` rows from the
|
|
409
|
+
* comment-thread source into this shape; activity_logs does NOT
|
|
410
|
+
* surface comments as its own events, so the cross-source merge
|
|
411
|
+
* is what unifies them.
|
|
412
|
+
*
|
|
413
|
+
* - `before: null` — comments are append-only events (no prior
|
|
414
|
+
* state).
|
|
415
|
+
* - `after.body` — `Update.body` (NON_NULL String per the probe).
|
|
416
|
+
* - `after.text_body` — `Update.text_body` (nullable; Monday's
|
|
417
|
+
* plain-text rendering of the rich-text body).
|
|
418
|
+
* - `after.reply_count` — count of `Update.replies` after the
|
|
419
|
+
* wire-side null-coalesce (Monday returns `null` for "no
|
|
420
|
+
* replies known"; the projector folds to `0` for agent
|
|
421
|
+
* ergonomics — see `mergeByCreatedAt` semantics).
|
|
422
|
+
*/
|
|
423
|
+
export const updatePostedEventSchema = z
|
|
424
|
+
.object({
|
|
425
|
+
...baseEventFields,
|
|
426
|
+
kind: z.literal('update_posted'),
|
|
427
|
+
before: z.null(),
|
|
428
|
+
after: z
|
|
429
|
+
.object({
|
|
430
|
+
body: z.string(),
|
|
431
|
+
text_body: z.string().nullable(),
|
|
432
|
+
reply_count: z.number().int().nonnegative(),
|
|
433
|
+
})
|
|
434
|
+
.strict(),
|
|
435
|
+
})
|
|
436
|
+
.strict();
|
|
437
|
+
/**
|
|
438
|
+
* **`update_replied`** — synthesized event for one reply within a
|
|
439
|
+
* comment thread. The projector emits ONE event per `Reply` row;
|
|
440
|
+
* the parent `Update.id` lands on `parent_update_id` so agents can
|
|
441
|
+
* reconstruct thread context without a second round-trip.
|
|
442
|
+
*
|
|
443
|
+
* `reply_kind` carries `Reply.kind` (NON_NULL String per the
|
|
444
|
+
* probe — a SEPARATE taxonomy from `activity_logs.event`). Pre-
|
|
445
|
+
* flight pins this as `z.string()` (open enum) per the same
|
|
446
|
+
* forward-compat policy as M23 favorites' `object.type` field —
|
|
447
|
+
* Monday may extend Reply.kind with new variants without breaking
|
|
448
|
+
* the parse.
|
|
449
|
+
*/
|
|
450
|
+
export const updateRepliedEventSchema = z
|
|
451
|
+
.object({
|
|
452
|
+
...baseEventFields,
|
|
453
|
+
kind: z.literal('update_replied'),
|
|
454
|
+
parent_update_id: z.string().min(1),
|
|
455
|
+
reply_kind: z.string().min(1),
|
|
456
|
+
before: z.null(),
|
|
457
|
+
after: z
|
|
458
|
+
.object({
|
|
459
|
+
body: z.string(),
|
|
460
|
+
text_body: z.string().nullable(),
|
|
461
|
+
})
|
|
462
|
+
.strict(),
|
|
463
|
+
})
|
|
464
|
+
.strict();
|
|
465
|
+
/**
|
|
466
|
+
* **`unknown`** — fallback variant for an `activity_logs.event`
|
|
467
|
+
* value the projector doesn't recognise. Carries the raw wire
|
|
468
|
+
* `event` slot (so agents see the unrecognised string) + the raw
|
|
469
|
+
* `entity` slot (so the walker filter discrepancy is visible) +
|
|
470
|
+
* the raw parsed `data` JSON under `after` (so a future-extension
|
|
471
|
+
* consumer can reproject without a second wire call). `before` is
|
|
472
|
+
* `null` for uniform shape with the synthesized comment-event
|
|
473
|
+
* variants (`update_posted` / `update_replied`) which also pin
|
|
474
|
+
* `before: null` for their append-only-events semantics — the
|
|
475
|
+
* `unknown` variant similarly has no meaningful "before" since the
|
|
476
|
+
* projector by definition doesn't know how to extract the prior
|
|
477
|
+
* state from the wire payload (the typed variants are the place
|
|
478
|
+
* that knowledge lives). Agents wanting to introspect the raw
|
|
479
|
+
* payload read `after` (the full parsed `data` JSON) alongside
|
|
480
|
+
* `event` + `entity` for routing.
|
|
481
|
+
*
|
|
482
|
+
* Surfaces alongside a `warnings[]` entry of code
|
|
483
|
+
* `unknown_event_kind` (per {@link buildUnknownEventKindWarning})
|
|
484
|
+
* so agents introspect the projector's coverage gap without parsing
|
|
485
|
+
* the events list for `kind === 'unknown'` themselves.
|
|
486
|
+
*
|
|
487
|
+
* Per Decision 2 closure: this variant is the registry-stable
|
|
488
|
+
* surface for forward-compat with Monday's expanding event
|
|
489
|
+
* taxonomy. The 29-error-code registry stays AT 29 — the unknown-
|
|
490
|
+
* event-kind surface is a `warnings[]` shape, NOT a new
|
|
491
|
+
* `error.code` entry.
|
|
492
|
+
*/
|
|
493
|
+
export const unknownEventSchema = z
|
|
494
|
+
.object({
|
|
495
|
+
...baseEventFields,
|
|
496
|
+
kind: z.literal('unknown'),
|
|
497
|
+
event: z.string().min(1),
|
|
498
|
+
entity: z.string().min(1),
|
|
499
|
+
before: z.null(),
|
|
500
|
+
after: z.unknown(),
|
|
501
|
+
})
|
|
502
|
+
.strict();
|
|
503
|
+
/**
|
|
504
|
+
* The projected per-event discriminated union — the contract surface
|
|
505
|
+
* for `monday item history`. Agents read `kind` to route per-variant
|
|
506
|
+
* handling. Adding a new variant is non-breaking (envelope-additive
|
|
507
|
+
* per §6.1); renaming or removing one is the SemVer-major boundary.
|
|
508
|
+
*
|
|
509
|
+
* **Variant count: 9** (1 item-scoped activity-log + 5 board-scoped
|
|
510
|
+
* activity-log variants kept for parser-roundtrip + 2 synthesized
|
|
511
|
+
* comment-thread variants + 1 unknown fallback). The Decision 2
|
|
512
|
+
* closure observed-events list capped the activity-log variants at
|
|
513
|
+
* 6; the synthesized + fallback variants are the projector's own
|
|
514
|
+
* contract.
|
|
515
|
+
*
|
|
516
|
+
* **Decision 2 ratification.** The discriminator field name `kind`
|
|
517
|
+
* maps 1:1 from Monday's wire `ActivityLogType.event` field
|
|
518
|
+
* (schema field-name drift); the variants enumerate the observed
|
|
519
|
+
* production taxonomy + the `unknown` fallback for forward-compat.
|
|
520
|
+
*/
|
|
521
|
+
export const historyEventSchema = z.discriminatedUnion('kind', [
|
|
522
|
+
updateColumnValueEventSchema,
|
|
523
|
+
createColumnEventSchema,
|
|
524
|
+
createGroupEventSchema,
|
|
525
|
+
updateBoardNameEventSchema,
|
|
526
|
+
updateBoardNicknameEventSchema,
|
|
527
|
+
boardWorkspaceIdChangedEventSchema,
|
|
528
|
+
updatePostedEventSchema,
|
|
529
|
+
updateRepliedEventSchema,
|
|
530
|
+
unknownEventSchema,
|
|
531
|
+
]);
|
|
532
|
+
/**
|
|
533
|
+
* The top-level command output schema — `data` is the chronologically-
|
|
534
|
+
* merged event array. Mirrors M23's `crossBoardSearchOutputSchema`
|
|
535
|
+
* (a flat array of typed rows; no top-level metadata in `data`).
|
|
536
|
+
*/
|
|
537
|
+
export const historyEventOutputSchema = z.array(historyEventSchema);
|
|
538
|
+
export const unknownEventKindWarningSchema = z
|
|
539
|
+
.object({
|
|
540
|
+
code: z.literal('unknown_event_kind'),
|
|
541
|
+
message: z.string().min(1),
|
|
542
|
+
details: z
|
|
543
|
+
.object({
|
|
544
|
+
event: z.string().min(1),
|
|
545
|
+
entity: z.string().min(1),
|
|
546
|
+
occurrence_count: z.number().int().positive(),
|
|
547
|
+
hint: z.string().min(1),
|
|
548
|
+
})
|
|
549
|
+
.strict(),
|
|
550
|
+
})
|
|
551
|
+
.strict();
|
|
552
|
+
/**
|
|
553
|
+
* Builds an {@link UnknownEventKindWarning} from one observed
|
|
554
|
+
* unknown event + its occurrence count across the merged stream.
|
|
555
|
+
* **Real implementation** at pre-flight (pure helper; the warning
|
|
556
|
+
* shape is the contract surface).
|
|
557
|
+
*
|
|
558
|
+
* The hint forward-references the projector's extensibility point
|
|
559
|
+
* so agents have a concrete next step (vs a generic "unknown"
|
|
560
|
+
* message that requires reading the source).
|
|
561
|
+
*/
|
|
562
|
+
export const buildUnknownEventKindWarning = (event, entity, occurrenceCount) => ({
|
|
563
|
+
code: 'unknown_event_kind',
|
|
564
|
+
message: `activity_logs returned ${String(occurrenceCount)} ${occurrenceCount === 1 ? 'row' : 'rows'} with an unrecognised event kind "${event}" (entity: "${entity}"); surfaced under the \`unknown\` event variant`,
|
|
565
|
+
details: {
|
|
566
|
+
event,
|
|
567
|
+
entity,
|
|
568
|
+
occurrence_count: occurrenceCount,
|
|
569
|
+
hint: 'Monday may have extended `activity_logs.event` with a new kind; extend `historyEventSchema` in `src/api/item-history-projection.ts` with a typed variant to surface the before/after payload, or consume the raw parsed payload from the `unknown` variant\'s `after` slot',
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
/**
|
|
573
|
+
* Merges two pre-projected event streams (activity-log + comment-
|
|
574
|
+
* thread) into a single chronologically-ordered stream. **Real
|
|
575
|
+
* implementation** at pre-flight (pure helper).
|
|
576
|
+
*
|
|
577
|
+
* Ordering rules:
|
|
578
|
+
* - Primary: `created_at` ascending (oldest first; matches
|
|
579
|
+
* Monday's UI activity log + comment thread chronological
|
|
580
|
+
* reading order).
|
|
581
|
+
* - Tie-break: `id` (lexicographic) — deterministic across runs
|
|
582
|
+
* even when two events share the exact same `created_at`
|
|
583
|
+
* timestamp (Monday's resolver issues IDs in monotonic order
|
|
584
|
+
* per source, so the tie-break preserves intra-source order).
|
|
585
|
+
*
|
|
586
|
+
* **Why merge here, not at the walker.** The two source walkers
|
|
587
|
+
* paginate independently (activity_logs page-numbered;
|
|
588
|
+
* updates page-numbered with a different denominator); merging at
|
|
589
|
+
* the walker would force coupled pagination on the streaming
|
|
590
|
+
* path. The projector merges the FULLY-DRAINED-PER-WALL-CLOCK-CAP
|
|
591
|
+
* lists — `fetchItemHistory` walks both sources to the `--since`
|
|
592
|
+
* / `--until` cap independently, then this helper merges.
|
|
593
|
+
*
|
|
594
|
+
* **Streaming semantics.** When `--stream` is on, the merge is
|
|
595
|
+
* NOT incremental — the entire `--since`-bounded slice must be
|
|
596
|
+
* resident to order it. The NDJSON stream emits the merged array
|
|
597
|
+
* per-item via the walker's `onItem` hook AFTER the merge
|
|
598
|
+
* completes; the trailer carries the per-source pagination state
|
|
599
|
+
* for resumption.
|
|
600
|
+
*/
|
|
601
|
+
export const mergeByCreatedAt = (activityEvents, commentEvents) => {
|
|
602
|
+
const merged = [...activityEvents, ...commentEvents];
|
|
603
|
+
return merged.sort((a, b) => {
|
|
604
|
+
if (a.created_at !== b.created_at) {
|
|
605
|
+
return a.created_at < b.created_at ? -1 : 1;
|
|
606
|
+
}
|
|
607
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
608
|
+
});
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Parses a wire `data` payload defensively. Monday encodes
|
|
612
|
+
* `ActivityLogType.data` as a JSON string carrying the per-event
|
|
613
|
+
* payload (per Decision 2 closure introspection). On parse failure
|
|
614
|
+
* the projector falls back to the raw string under
|
|
615
|
+
* `{raw_data: <string>}` so the `unknown` variant's `after` slot
|
|
616
|
+
* still carries diagnostic content rather than a discarded payload.
|
|
617
|
+
*/
|
|
618
|
+
const parseActivityLogDataJson = (raw) => {
|
|
619
|
+
try {
|
|
620
|
+
return JSON.parse(raw);
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
return { raw_data: raw };
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
/**
|
|
627
|
+
* Extracts `value` / `previous_value` from a Monday `data` payload.
|
|
628
|
+
* The wire shape carries them as JSON-encoded strings inside the
|
|
629
|
+
* outer parsed object (Monday's nested-JSON convention); the
|
|
630
|
+
* projector unwraps one level so agents see the structured payload
|
|
631
|
+
* (e.g. `{label, index}`, `{date, time}`) rather than an opaque
|
|
632
|
+
* string. When the slot is already a structured value (Monday's
|
|
633
|
+
* shape varies per column type and per event), pass it through.
|
|
634
|
+
*
|
|
635
|
+
* Per Decision 2 closure: `previous_value` is sometimes `{}` on
|
|
636
|
+
* first-set events ("previously-unset"). The projector preserves
|
|
637
|
+
* the empty-object shape rather than collapsing to `null` — agents
|
|
638
|
+
* keying off the empty-object distinguish "first set" from
|
|
639
|
+
* "no prior value tracked".
|
|
640
|
+
*/
|
|
641
|
+
const unwrapNestedJson = (value) => {
|
|
642
|
+
if (typeof value !== 'string')
|
|
643
|
+
return value;
|
|
644
|
+
try {
|
|
645
|
+
return JSON.parse(value);
|
|
646
|
+
}
|
|
647
|
+
catch {
|
|
648
|
+
return value;
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
/**
|
|
652
|
+
* Reads `column_id` / `column_type` from a parsed `data` payload.
|
|
653
|
+
* Both fields are required for the `update_column_value` typed
|
|
654
|
+
* variant per Decision 2 closure (the wire payload always carries
|
|
655
|
+
* them for item-scoped column-edit events). Missing / non-string
|
|
656
|
+
* slots fall back to empty strings — the projector then routes the
|
|
657
|
+
* row through the `unknown` fallback rather than emitting a typed
|
|
658
|
+
* variant with an empty discriminator.
|
|
659
|
+
*/
|
|
660
|
+
const readStringField = (obj, key) => {
|
|
661
|
+
const v = obj[key];
|
|
662
|
+
return typeof v === 'string' ? v : '';
|
|
663
|
+
};
|
|
664
|
+
const readNullableString = (obj, key) => {
|
|
665
|
+
const v = obj[key];
|
|
666
|
+
return typeof v === 'string' ? v : null;
|
|
667
|
+
};
|
|
668
|
+
/**
|
|
669
|
+
* Reads a Monday ID field that the wire emits as either a string
|
|
670
|
+
* or an unquoted JSON number. The Decision 2 probe shows
|
|
671
|
+
* `update_column_value.pulse_id` ships as a `<number>` JSON
|
|
672
|
+
* literal on the wire; the Update / Reply surfaces ship the same
|
|
673
|
+
* id-shaped slots as strings. Both need to land on the projected
|
|
674
|
+
* event as `string | null` (the CLI's branded `ItemId` shape +
|
|
675
|
+
* agent ergonomics — JSON IDs are stringified throughout the
|
|
676
|
+
* envelope to avoid floating-point precision issues on large
|
|
677
|
+
* board / item / pulse identifiers).
|
|
678
|
+
*
|
|
679
|
+
* Codex impl review round 2 P2-1: without this helper,
|
|
680
|
+
* `readNullableString` rejected the numeric wire shape and the
|
|
681
|
+
* projected event would carry `pulse_id: null` despite the
|
|
682
|
+
* probe-confirmed wire value.
|
|
683
|
+
*/
|
|
684
|
+
const readNullableIdField = (obj, key) => {
|
|
685
|
+
const v = obj[key];
|
|
686
|
+
if (typeof v === 'string')
|
|
687
|
+
return v;
|
|
688
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
689
|
+
return String(v);
|
|
690
|
+
return null;
|
|
691
|
+
};
|
|
692
|
+
/**
|
|
693
|
+
* Projects one wire `ActivityLogType` row into a typed
|
|
694
|
+
* {@link HistoryEvent}. Parses the wire `data` JSON, dispatches
|
|
695
|
+
* on `row.event`, and emits the matching typed variant. Unknown
|
|
696
|
+
* event kinds fall back to the `unknown` variant carrying the raw
|
|
697
|
+
* parsed `data` under `after`.
|
|
698
|
+
*
|
|
699
|
+
* The projector is the SINGLE per-row dispatch point; the walker
|
|
700
|
+
* delegates to it after the `entity === 'pulse'` filter (single
|
|
701
|
+
* source of truth at the walker layer per Decision 2 closure;
|
|
702
|
+
* projector does NOT re-filter).
|
|
703
|
+
*
|
|
704
|
+
* Per-`column_type` typed before/after for `update_column_value`:
|
|
705
|
+
* `value` and `previous_value` are passed through with one level
|
|
706
|
+
* of nested-JSON unwrap (Monday encodes nested values as JSON
|
|
707
|
+
* strings inside the outer `data` payload); each column type's
|
|
708
|
+
* concrete payload shape (e.g. status `{label, index}`, date ISO
|
|
709
|
+
* string, text raw string) flows through unchanged. Per Decision
|
|
710
|
+
* 2 closure: `previous_value: {}` is preserved as "previously-
|
|
711
|
+
* unset" rather than collapsed to `null` — agents distinguish
|
|
712
|
+
* the empty-object shape.
|
|
713
|
+
*/
|
|
714
|
+
export const projectActivityLogRow = (inputs) => {
|
|
715
|
+
const { row } = inputs;
|
|
716
|
+
const parsedData = parseActivityLogDataJson(row.data);
|
|
717
|
+
const dataObj = isPlainObject(parsedData) ? parsedData : {};
|
|
718
|
+
switch (row.event) {
|
|
719
|
+
case 'update_column_value': {
|
|
720
|
+
const columnId = readStringField(dataObj, 'column_id');
|
|
721
|
+
const columnType = readStringField(dataObj, 'column_type');
|
|
722
|
+
// Missing / empty discriminator fields → fall through to
|
|
723
|
+
// `unknown` rather than emit a typed variant with empty
|
|
724
|
+
// strings. Defensive: the probe pinned both fields always
|
|
725
|
+
// present on `update_column_value` payloads, but a future
|
|
726
|
+
// Monday rename or partial-payload bug would otherwise
|
|
727
|
+
// produce a malformed typed event.
|
|
728
|
+
if (columnId !== '' && columnType !== '') {
|
|
729
|
+
return {
|
|
730
|
+
id: row.id,
|
|
731
|
+
created_at: row.created_at,
|
|
732
|
+
actor_id: row.user_id,
|
|
733
|
+
kind: 'update_column_value',
|
|
734
|
+
column_id: columnId,
|
|
735
|
+
column_type: columnType,
|
|
736
|
+
before: unwrapNestedJson(dataObj.previous_value),
|
|
737
|
+
after: unwrapNestedJson(dataObj.value),
|
|
738
|
+
textual_value: readNullableString(dataObj, 'textual_value'),
|
|
739
|
+
pulse_id: readNullableIdField(dataObj, 'pulse_id'),
|
|
740
|
+
pulse_name: readNullableString(dataObj, 'pulse_name'),
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
case 'create_column':
|
|
746
|
+
case 'create_group':
|
|
747
|
+
case 'update_board_name':
|
|
748
|
+
case 'update_board_nickname':
|
|
749
|
+
case 'board_workspace_id_changed': {
|
|
750
|
+
// Board-scoped variants — the walker's entity filter
|
|
751
|
+
// normally drops these, but the projector keeps the typed
|
|
752
|
+
// branch so a future regression that bypasses the filter
|
|
753
|
+
// fails into the typed variant rather than `unknown`.
|
|
754
|
+
// Both `before` / `after` carry the raw parsed payload so
|
|
755
|
+
// agents see Monday's full event payload without re-parsing.
|
|
756
|
+
return {
|
|
757
|
+
id: row.id,
|
|
758
|
+
created_at: row.created_at,
|
|
759
|
+
actor_id: row.user_id,
|
|
760
|
+
kind: row.event,
|
|
761
|
+
before: unwrapNestedJson(dataObj.previous_value),
|
|
762
|
+
after: parsedData,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
default: // fall through to the unknown variant below.
|
|
766
|
+
}
|
|
767
|
+
return {
|
|
768
|
+
id: row.id,
|
|
769
|
+
created_at: row.created_at,
|
|
770
|
+
actor_id: row.user_id,
|
|
771
|
+
kind: 'unknown',
|
|
772
|
+
event: row.event,
|
|
773
|
+
entity: row.entity,
|
|
774
|
+
before: null,
|
|
775
|
+
after: parsedData,
|
|
776
|
+
};
|
|
777
|
+
};
|
|
778
|
+
/**
|
|
779
|
+
* Projects one wire `Update` row into a synthesized
|
|
780
|
+
* {@link HistoryEvent} of kind `update_posted` plus one
|
|
781
|
+
* `update_replied` event per `row.replies` entry (via
|
|
782
|
+
* {@link projectReplyRow}). Returns a flat array suitable for
|
|
783
|
+
* the merger.
|
|
784
|
+
*
|
|
785
|
+
* `Update.created_at` is nullable per Decision 2 closure probe
|
|
786
|
+
* findings; the projector substitutes `Update.edited_at`
|
|
787
|
+
* (NON_NULL) as the chronological key — silent projection
|
|
788
|
+
* behaviour, deterministic across re-walks.
|
|
789
|
+
*
|
|
790
|
+
* Replies are flat-mapped here (not at the walker) so the
|
|
791
|
+
* walker stays surface-symmetric with the activity_logs source
|
|
792
|
+
* (both project per-row → events). The merge projector orders
|
|
793
|
+
* the combined stream.
|
|
794
|
+
*/
|
|
795
|
+
export const projectUpdateRow = (inputs) => {
|
|
796
|
+
const { row } = inputs;
|
|
797
|
+
const createdAt = row.created_at ?? row.edited_at;
|
|
798
|
+
const replies = row.replies ?? [];
|
|
799
|
+
const posted = {
|
|
800
|
+
id: row.id,
|
|
801
|
+
created_at: createdAt,
|
|
802
|
+
actor_id: row.creator_id,
|
|
803
|
+
kind: 'update_posted',
|
|
804
|
+
before: null,
|
|
805
|
+
after: {
|
|
806
|
+
body: row.body,
|
|
807
|
+
text_body: row.text_body,
|
|
808
|
+
reply_count: replies.length,
|
|
809
|
+
},
|
|
810
|
+
};
|
|
811
|
+
const repliedEvents = replies.map((reply) => projectReplyRow({
|
|
812
|
+
row: reply,
|
|
813
|
+
parentUpdateId: row.id,
|
|
814
|
+
parentCreatedAt: createdAt,
|
|
815
|
+
}));
|
|
816
|
+
return [posted, ...repliedEvents];
|
|
817
|
+
};
|
|
818
|
+
/**
|
|
819
|
+
* Projects one wire `Reply` row into a synthesized
|
|
820
|
+
* {@link HistoryEvent} of kind `update_replied`. The parent
|
|
821
|
+
* `Update.id` lands on `parent_update_id`; `Reply.kind` lands on
|
|
822
|
+
* `reply_kind` (separate from `activity_logs.event` taxonomy per
|
|
823
|
+
* the Decision 2 closure probe finding).
|
|
824
|
+
*
|
|
825
|
+
* `Reply.created_at` is nullable per the probe introspection;
|
|
826
|
+
* fallback chain: `Reply.created_at` → `Reply.updated_at` →
|
|
827
|
+
* the parent Update's projected timestamp. The final fallback
|
|
828
|
+
* is load-bearing: the event schema requires `created_at` to be
|
|
829
|
+
* non-empty (`min(1)`) and the parent's timestamp is guaranteed
|
|
830
|
+
* non-empty by `projectUpdateRow`'s `created_at ?? edited_at`
|
|
831
|
+
* resolution (Codex impl review round 1 P2-2). A Reply with both
|
|
832
|
+
* timestamps null then merges right next to its parent on the
|
|
833
|
+
* chronological stream.
|
|
834
|
+
*/
|
|
835
|
+
export const projectReplyRow = (inputs) => {
|
|
836
|
+
const { row, parentUpdateId, parentCreatedAt } = inputs;
|
|
837
|
+
const createdAt = row.created_at ?? row.updated_at ?? parentCreatedAt;
|
|
838
|
+
return {
|
|
839
|
+
id: row.id,
|
|
840
|
+
created_at: createdAt,
|
|
841
|
+
actor_id: row.creator_id,
|
|
842
|
+
kind: 'update_replied',
|
|
843
|
+
parent_update_id: parentUpdateId,
|
|
844
|
+
reply_kind: row.kind,
|
|
845
|
+
before: null,
|
|
846
|
+
after: {
|
|
847
|
+
body: row.body,
|
|
848
|
+
text_body: row.text_body,
|
|
849
|
+
},
|
|
850
|
+
};
|
|
851
|
+
};
|
|
852
|
+
/**
|
|
853
|
+
* Two-source GraphQL response schemas — parse boundaries for the
|
|
854
|
+
* walker's per-stage `unwrapOrThrow` calls. `.loose()` lets
|
|
855
|
+
* additive Monday surface fields pass through without breaking
|
|
856
|
+
* the parse (same forward-compat policy as M22/M23 wire schemas).
|
|
857
|
+
*/
|
|
858
|
+
const activityLogsResponseSchema = z
|
|
859
|
+
.object({
|
|
860
|
+
boards: z
|
|
861
|
+
.array(z
|
|
862
|
+
.object({
|
|
863
|
+
id: z.string().min(1),
|
|
864
|
+
activity_logs: z.array(rawActivityLogRowSchema).nullable(),
|
|
865
|
+
})
|
|
866
|
+
.loose()
|
|
867
|
+
.nullable())
|
|
868
|
+
.nullable(),
|
|
869
|
+
})
|
|
870
|
+
.loose();
|
|
871
|
+
const updatesResponseSchema = z
|
|
872
|
+
.object({
|
|
873
|
+
items: z
|
|
874
|
+
.array(z
|
|
875
|
+
.object({
|
|
876
|
+
id: z.string().min(1),
|
|
877
|
+
updates: z.array(rawUpdateRowSchema).nullable(),
|
|
878
|
+
})
|
|
879
|
+
.loose()
|
|
880
|
+
.nullable())
|
|
881
|
+
.nullable(),
|
|
882
|
+
})
|
|
883
|
+
.loose();
|
|
884
|
+
/**
|
|
885
|
+
* Tests whether an ISO-8601 timestamp falls within the
|
|
886
|
+
* `--since` / `--until` range. Uses `Date.parse` rather than
|
|
887
|
+
* lexicographic compare because the wire payload may carry
|
|
888
|
+
* UTC `Z`-suffixed timestamps (Monday's `ISO8601DateTime`
|
|
889
|
+
* scalar — Decision 2 probe) while the CLI's `--since` /
|
|
890
|
+
* `--until` accept any ISO-8601 surface, including mixed
|
|
891
|
+
* offsets (`+01:00`, `-05:00`, etc.). Lex compare gives the
|
|
892
|
+
* wrong answer when offsets differ — e.g. `09:30:00Z` should
|
|
893
|
+
* pass `--since 10:00:00+01:00` (= 09:00:00Z) but lex compare
|
|
894
|
+
* would reject it (Codex impl review round 1 P2-1).
|
|
895
|
+
*
|
|
896
|
+
* `since` / `until` epoch values are precomputed by the caller
|
|
897
|
+
* to avoid the per-row Date.parse cost on large slices.
|
|
898
|
+
*
|
|
899
|
+
* **NaN guard.** `Date.parse` returns `NaN` on malformed input.
|
|
900
|
+
* All `NaN`-vs-number comparisons are `false`, so without a
|
|
901
|
+
* guard a malformed row timestamp would slip through the filter
|
|
902
|
+
* (Codex impl review round 2 P3-1). The walker's argv schema
|
|
903
|
+
* filters user-supplied bounds upstream, but the row epoch is
|
|
904
|
+
* sourced from Monday's wire and may drift if Monday ships a
|
|
905
|
+
* malformed `Update.created_at`. Treat unparseable rows as
|
|
906
|
+
* out-of-range so the merger doesn't surface them.
|
|
907
|
+
*/
|
|
908
|
+
const inWallClockRange = (timestamp, sinceEpoch, untilEpoch) => {
|
|
909
|
+
const epoch = Date.parse(timestamp);
|
|
910
|
+
if (Number.isNaN(epoch))
|
|
911
|
+
return false;
|
|
912
|
+
if (sinceEpoch !== undefined && epoch < sinceEpoch)
|
|
913
|
+
return false;
|
|
914
|
+
if (untilEpoch !== undefined && epoch > untilEpoch)
|
|
915
|
+
return false;
|
|
916
|
+
return true;
|
|
917
|
+
};
|
|
918
|
+
/**
|
|
919
|
+
* Two-source merged-history walker. Issues two independent
|
|
920
|
+
* GraphQL calls (activity_logs + updates), filters + projects
|
|
921
|
+
* each per Decision 2 closure ratified shape, merges
|
|
922
|
+
* chronologically, aggregates `unknown_event_kind` warnings,
|
|
923
|
+
* applies optional `--kinds` projection filter, and streams via
|
|
924
|
+
* `inputs.onItem` (per-merged-event AFTER the merge — merging
|
|
925
|
+
* requires full slice resident per the `mergeByCreatedAt`
|
|
926
|
+
* docstring).
|
|
927
|
+
*
|
|
928
|
+
* **`source: 'live'` constant.** activity_logs + updates are
|
|
929
|
+
* pure reads with no per-call cache; the action layer aggregates
|
|
930
|
+
* this with the item-board lookup's `'live'` source via
|
|
931
|
+
* `SourceAggregator` and resolves the envelope's `meta.source`
|
|
932
|
+
* from the aggregator's resolved state (mirrors M23
|
|
933
|
+
* cross-board-search).
|
|
934
|
+
*
|
|
935
|
+
* **`complexity`** is the larger of the two stages' per-call
|
|
936
|
+
* complexity values (under `--verbose` only; null outside). Two
|
|
937
|
+
* independent calls → take the worst-case stage so agents see
|
|
938
|
+
* the more conservative budget snapshot rather than averaging.
|
|
939
|
+
*
|
|
940
|
+
* **Per-source pagination state.** Each source's `last_page` is
|
|
941
|
+
* the page number the walker DRAINED if the response returned a
|
|
942
|
+
* full slice (`response.length === limit` → more pages likely);
|
|
943
|
+
* `null` when the response returned less than `limit` rows
|
|
944
|
+
* (source exhausted). Monday's page-numbered surfaces have no
|
|
945
|
+
* "next" sentinel; the heuristic mirrors the v0.2 page-walker
|
|
946
|
+
* shape.
|
|
947
|
+
*/
|
|
948
|
+
export const fetchItemHistory = async (inputs) => {
|
|
949
|
+
const limit = inputs.limit ?? DEFAULT_HISTORY_PAGE_SIZE;
|
|
950
|
+
const activityPage = inputs.activityLogsPage ?? 1;
|
|
951
|
+
const updatesPage = inputs.updatesPage ?? 1;
|
|
952
|
+
// Stage 1 — activity_logs page-walk.
|
|
953
|
+
const stage1 = await inputs.client.raw(ACTIVITY_LOGS_QUERY, {
|
|
954
|
+
bid: [inputs.boardId],
|
|
955
|
+
iid: [inputs.itemId],
|
|
956
|
+
// Monday's `from` / `to` accept null for unbounded sides; we
|
|
957
|
+
// omit the key entirely when undefined to keep the wire
|
|
958
|
+
// payload minimal (the `.loose()` parse on the response is
|
|
959
|
+
// unaffected by which args we send).
|
|
960
|
+
...(inputs.since === undefined ? {} : { from: inputs.since }),
|
|
961
|
+
...(inputs.until === undefined ? {} : { to: inputs.until }),
|
|
962
|
+
page: activityPage,
|
|
963
|
+
limit,
|
|
964
|
+
}, { operationName: 'ItemHistoryActivityLogs' });
|
|
965
|
+
const stage1Data = unwrapOrThrow(activityLogsResponseSchema.safeParse(stage1.data), {
|
|
966
|
+
context: 'Monday `boards.activity_logs` response',
|
|
967
|
+
details: { item_id: inputs.itemId, board_id: inputs.boardId },
|
|
968
|
+
hint: 'Monday may have amended the `boards(ids:) { activity_logs }` surface — re-probe via `scripts/probe/m24-history-kinds.ts` and amend cli-design §13 v0.3 entry if so',
|
|
969
|
+
});
|
|
970
|
+
const rawActivityRows = [];
|
|
971
|
+
const boards = stage1Data.boards ?? [];
|
|
972
|
+
for (const board of boards) {
|
|
973
|
+
if (board === null)
|
|
974
|
+
continue;
|
|
975
|
+
const rows = board.activity_logs ?? [];
|
|
976
|
+
rawActivityRows.push(...rows);
|
|
977
|
+
}
|
|
978
|
+
// Walker-side entity filter (Decision 2 ratified): drop
|
|
979
|
+
// board-scoped events that leak through `item_ids` per the
|
|
980
|
+
// empirical-probe finding. Single source of truth at the walker;
|
|
981
|
+
// projector does NOT re-filter.
|
|
982
|
+
const itemScopedRows = rawActivityRows.filter((r) => r.entity === ITEM_SCOPED_ENTITY);
|
|
983
|
+
const activityEvents = itemScopedRows.map((row) => projectActivityLogRow({ row }));
|
|
984
|
+
// Aggregate unknown_event_kind warnings: one warning per unique
|
|
985
|
+
// (event, entity) tuple observed; `occurrence_count` carries the
|
|
986
|
+
// multiplicity so the warnings array stays bounded on degenerate
|
|
987
|
+
// inputs. Keyed by `${event}\x00${entity}` to disambiguate the
|
|
988
|
+
// same event name surfacing under two entity values.
|
|
989
|
+
const unknownByKey = new Map();
|
|
990
|
+
for (const ev of activityEvents) {
|
|
991
|
+
if (ev.kind === 'unknown') {
|
|
992
|
+
const key = `${ev.event}\x00${ev.entity}`;
|
|
993
|
+
const entry = unknownByKey.get(key);
|
|
994
|
+
if (entry === undefined) {
|
|
995
|
+
unknownByKey.set(key, {
|
|
996
|
+
event: ev.event,
|
|
997
|
+
entity: ev.entity,
|
|
998
|
+
count: 1,
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
else {
|
|
1002
|
+
entry.count++;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
// Stage 2 — updates page-walk (independent denominator).
|
|
1007
|
+
const stage2 = await inputs.client.raw(UPDATES_QUERY, {
|
|
1008
|
+
iid: [inputs.itemId],
|
|
1009
|
+
page: updatesPage,
|
|
1010
|
+
limit,
|
|
1011
|
+
}, { operationName: 'ItemHistoryUpdates' });
|
|
1012
|
+
const stage2Data = unwrapOrThrow(updatesResponseSchema.safeParse(stage2.data), {
|
|
1013
|
+
context: 'Monday `items.updates` response',
|
|
1014
|
+
details: { item_id: inputs.itemId },
|
|
1015
|
+
hint: 'Monday may have amended the `items(ids:) { updates }` surface — re-probe via `scripts/probe/m24-history-kinds.ts` and amend cli-design §13 v0.3 entry if so',
|
|
1016
|
+
});
|
|
1017
|
+
const rawUpdateRows = [];
|
|
1018
|
+
const items = stage2Data.items ?? [];
|
|
1019
|
+
for (const it of items) {
|
|
1020
|
+
if (it === null)
|
|
1021
|
+
continue;
|
|
1022
|
+
const rows = it.updates ?? [];
|
|
1023
|
+
rawUpdateRows.push(...rows);
|
|
1024
|
+
}
|
|
1025
|
+
// Project each Update + flat-map its replies. The projector
|
|
1026
|
+
// returns a flat array (parent + N replies) per row; flat-map
|
|
1027
|
+
// here so the wall-clock filter and merger see one combined
|
|
1028
|
+
// list per source.
|
|
1029
|
+
const allUpdateEvents = rawUpdateRows.flatMap((row) => projectUpdateRow({ row }));
|
|
1030
|
+
// Client-side wall-clock filter. Monday's `updates` resolver
|
|
1031
|
+
// doesn't expose `from:` / `to:` per Decision 2 probe; filter
|
|
1032
|
+
// after projection so the per-row chronological key matches the
|
|
1033
|
+
// merger's sort. Precompute epoch bounds once so we don't pay
|
|
1034
|
+
// the `Date.parse(bound)` cost per row.
|
|
1035
|
+
const sinceEpoch = inputs.since === undefined ? undefined : Date.parse(inputs.since);
|
|
1036
|
+
const untilEpoch = inputs.until === undefined ? undefined : Date.parse(inputs.until);
|
|
1037
|
+
const updateEvents = sinceEpoch === undefined && untilEpoch === undefined
|
|
1038
|
+
? allUpdateEvents
|
|
1039
|
+
: allUpdateEvents.filter((ev) => inWallClockRange(ev.created_at, sinceEpoch, untilEpoch));
|
|
1040
|
+
// Chronological merge of both fully-drained source lists.
|
|
1041
|
+
const merged = mergeByCreatedAt(activityEvents, updateEvents);
|
|
1042
|
+
// Optional `--kinds` projection filter — narrows `data` array
|
|
1043
|
+
// but warnings stay (per the docstring contract). Set lookup
|
|
1044
|
+
// keeps the filter O(N).
|
|
1045
|
+
const kindsSet = inputs.kinds === undefined ? undefined : new Set(inputs.kinds);
|
|
1046
|
+
const filtered = kindsSet === undefined
|
|
1047
|
+
? merged
|
|
1048
|
+
: merged.filter((ev) => kindsSet.has(ev.kind));
|
|
1049
|
+
// Stream hook — per-merged-event AFTER the merge (merging is
|
|
1050
|
+
// not incremental per the helper's docstring). Awaiting each
|
|
1051
|
+
// call preserves backpressure when the hook drives an NDJSON
|
|
1052
|
+
// stream against a slow consumer.
|
|
1053
|
+
if (inputs.onItem !== undefined) {
|
|
1054
|
+
for (const event of filtered) {
|
|
1055
|
+
await inputs.onItem(event);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
// Build warnings array — sorted deterministically by event so
|
|
1059
|
+
// re-walks against the same wire produce identical envelopes.
|
|
1060
|
+
// Entity disambiguation lives in the map key (defensive against
|
|
1061
|
+
// a future bypass of the walker's entity filter) but the sort
|
|
1062
|
+
// is primary-on-event only: the walker's `entity === 'pulse'`
|
|
1063
|
+
// filter means every surfaced warning carries entity='pulse'
|
|
1064
|
+
// in production, so a secondary entity sort would be dead code.
|
|
1065
|
+
const warnings = Array.from(unknownByKey.values())
|
|
1066
|
+
.sort((a, b) => (a.event < b.event ? -1 : a.event > b.event ? 1 : 0))
|
|
1067
|
+
.map((entry) => buildUnknownEventKindWarning(entry.event, entry.entity, entry.count));
|
|
1068
|
+
// Per-source pagination state. Heuristic: a response of less
|
|
1069
|
+
// than `limit` rows means "drained" → last_page null; a full
|
|
1070
|
+
// slice means "potentially more" → last_page = current page.
|
|
1071
|
+
const activityLastPage = rawActivityRows.length < limit ? null : activityPage;
|
|
1072
|
+
const updatesLastPage = rawUpdateRows.length < limit ? null : updatesPage;
|
|
1073
|
+
// Complexity — worst-case (smaller) of the two stages'
|
|
1074
|
+
// `remaining` budget under `--verbose`; null outside. Two
|
|
1075
|
+
// independent calls → pick the stage that consumed the most
|
|
1076
|
+
// budget so agents see the more conservative remaining
|
|
1077
|
+
// snapshot rather than averaging.
|
|
1078
|
+
const complexity = stage1.complexity === null
|
|
1079
|
+
? stage2.complexity
|
|
1080
|
+
: stage2.complexity === null
|
|
1081
|
+
? stage1.complexity
|
|
1082
|
+
: stage1.complexity.remaining <= stage2.complexity.remaining
|
|
1083
|
+
? stage1.complexity
|
|
1084
|
+
: stage2.complexity;
|
|
1085
|
+
return {
|
|
1086
|
+
events: filtered,
|
|
1087
|
+
pagination: {
|
|
1088
|
+
activity_logs: { last_page: activityLastPage },
|
|
1089
|
+
updates: { last_page: updatesLastPage },
|
|
1090
|
+
},
|
|
1091
|
+
warnings,
|
|
1092
|
+
complexity,
|
|
1093
|
+
source: 'live',
|
|
1094
|
+
};
|
|
1095
|
+
};
|
|
1096
|
+
/**
|
|
1097
|
+
* Adapter from a {@link FetchItemHistoryResult}'s `warnings`
|
|
1098
|
+
* array to the envelope-shaped {@link Warning} array consumed by
|
|
1099
|
+
* `emitSuccess`. Pre-flight pure helper — type-narrows the
|
|
1100
|
+
* `code` discriminator so the envelope's `warnings[]` slot
|
|
1101
|
+
* carries the precise shape rather than a generic `Warning`.
|
|
1102
|
+
*/
|
|
1103
|
+
export const toEnvelopeWarnings = (warnings) => warnings;
|
|
1104
|
+
//# sourceMappingURL=item-history-projection.js.map
|