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,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth flow primitives for the v0.3-M21 `monday auth login` /
|
|
3
|
+
* `monday auth logout` verbs (cli-design §7.3 / §7.4).
|
|
4
|
+
*
|
|
5
|
+
* **Empirical probe findings (2026-05-10, against `auth.monday.com`):**
|
|
6
|
+
*
|
|
7
|
+
* - `/oauth2/authorize` accepts arbitrary query params and encodes
|
|
8
|
+
* them all into a JWT-signed `oauth_payload_token`, then 302-
|
|
9
|
+
* redirects to `https://auth.monday.com/login?oauth_payload_token=<jwt>`.
|
|
10
|
+
* Extra params like `code_challenge` + `code_challenge_method=S256`
|
|
11
|
+
* are silently round-tripped through the JWT but **not enforced**
|
|
12
|
+
* at token-exchange time — Monday's `/oauth2/token` requires
|
|
13
|
+
* `client_secret` regardless. Verbatim probe response when the
|
|
14
|
+
* PKCE-shape exchange omits `client_secret`:
|
|
15
|
+
* `{"error":"invalid_request","error_description":"Missing client_secret param"}`
|
|
16
|
+
* (status 400). PKCE is therefore **not load-bearing for v0.3**;
|
|
17
|
+
* the design ships without `code_challenge` / `code_verifier`.
|
|
18
|
+
*
|
|
19
|
+
* - `/oauth2/token` rejection responses follow RFC 6749 standard
|
|
20
|
+
* shape (status 400, `application/json; charset=utf-8`):
|
|
21
|
+
* `{"error": "<code>", "error_description": "<text>"}`.
|
|
22
|
+
*
|
|
23
|
+
* - Redirect URI matching is documented as exact (Monday Apps
|
|
24
|
+
* OAuth docs); design ships fixed-port `127.0.0.1:9876`.
|
|
25
|
+
*
|
|
26
|
+
* - Token response shape per Monday's docs:
|
|
27
|
+
* `{access_token, token_type, scope}`. **No `expires_in`**;
|
|
28
|
+
* Monday tokens "do not expire and are valid until the user
|
|
29
|
+
* uninstalls your app".
|
|
30
|
+
*
|
|
31
|
+
* **OAuth client registration (M21 implementation Part 1).**
|
|
32
|
+
* `OAUTH_CLIENT_ID` + `OAUTH_CLIENT_SECRET` are pinned in source
|
|
33
|
+
* per the public-OAuth-client convention — the secret authenticates
|
|
34
|
+
* the *app* (monday-cli), not the user. The user's flow is
|
|
35
|
+
* protected by the per-attempt `state` CSRF token + the listener-
|
|
36
|
+
* bound `redirect_uri`. **Until an OAuth app is registered with
|
|
37
|
+
* Monday's developer portal, the constants below carry placeholder
|
|
38
|
+
* values; production users see `oauth_failed.reason:
|
|
39
|
+
* "code_exchange_failed"` until they're swapped pre-publish.**
|
|
40
|
+
*/
|
|
41
|
+
/** Monday Apps OAuth authorize endpoint. */
|
|
42
|
+
export declare const OAUTH_AUTHORIZE_URL = "https://auth.monday.com/oauth2/authorize";
|
|
43
|
+
/** Monday Apps OAuth token-exchange endpoint. */
|
|
44
|
+
export declare const OAUTH_TOKEN_URL = "https://auth.monday.com/oauth2/token";
|
|
45
|
+
/**
|
|
46
|
+
* Default port for the local-loopback OAuth callback listener. Pinned
|
|
47
|
+
* to `9876` to match cli-design §7.3.1 step 2; the OAuth app's
|
|
48
|
+
* redirect URI configuration pins this port.
|
|
49
|
+
*/
|
|
50
|
+
export declare const OAUTH_DEFAULT_PORT = 9876;
|
|
51
|
+
/** Path the listener answers; the OAuth app's redirect URI pins this. */
|
|
52
|
+
export declare const OAUTH_CALLBACK_PATH = "/callback";
|
|
53
|
+
/** Default listener timeout: 5 minutes (cli-design §7.3.1 step 4). */
|
|
54
|
+
export declare const OAUTH_DEFAULT_LISTENER_TIMEOUT_MS: number;
|
|
55
|
+
/**
|
|
56
|
+
* **PLACEHOLDER — replace with the registered Monday OAuth app's
|
|
57
|
+
* client_id pre-publish.** Tests do not depend on the value
|
|
58
|
+
* (cassettes intercept `/oauth2/token`); production users hit
|
|
59
|
+
* `oauth_failed.reason: "code_exchange_failed"` until swapped.
|
|
60
|
+
*
|
|
61
|
+
* Register at https://developer.monday.com/apps with redirect URI
|
|
62
|
+
* exactly `http://127.0.0.1:9876/callback`.
|
|
63
|
+
*/
|
|
64
|
+
export declare const OAUTH_CLIENT_ID = "<UNREGISTERED_PENDING_OAUTH_APP>";
|
|
65
|
+
/**
|
|
66
|
+
* **PLACEHOLDER — replace alongside {@link OAUTH_CLIENT_ID}.** Same
|
|
67
|
+
* pre-publish swap; see {@link OAUTH_CLIENT_ID} for context.
|
|
68
|
+
*/
|
|
69
|
+
export declare const OAUTH_CLIENT_SECRET = "<UNREGISTERED_PENDING_OAUTH_APP>";
|
|
70
|
+
/**
|
|
71
|
+
* Sentinel value the placeholder constants ship as until a Monday
|
|
72
|
+
* OAuth app is registered (see {@link OAUTH_CLIENT_ID} docstring).
|
|
73
|
+
* Exposed as a deliberately-widened `string` so consumers can compare
|
|
74
|
+
* `OAUTH_CLIENT_ID === OAUTH_UNREGISTERED_PLACEHOLDER` without
|
|
75
|
+
* triggering `@typescript-eslint/no-unnecessary-condition` on
|
|
76
|
+
* literal-vs-literal equality. v0.3-plan §8 Decision 11 rejected the
|
|
77
|
+
* v0.3 OAuth swap; the placeholder + guard in
|
|
78
|
+
* `src/commands/auth/login.ts` together surface a clear `usage_error`
|
|
79
|
+
* pointing users at `MONDAY_API_TOKEN` until a future version
|
|
80
|
+
* revisits the OAuth path.
|
|
81
|
+
*/
|
|
82
|
+
export declare const OAUTH_UNREGISTERED_PLACEHOLDER: string;
|
|
83
|
+
/**
|
|
84
|
+
* Documented Monday Apps OAuth scopes per Monday's published docs at
|
|
85
|
+
* the M21 pre-flight probe (2026-05-10). Each entry is exposed
|
|
86
|
+
* verbatim so the OAuth-app-registration step (M21 implementation
|
|
87
|
+
* Part 1) can request the subset the CLI actually needs without a
|
|
88
|
+
* second source-of-truth elsewhere.
|
|
89
|
+
*/
|
|
90
|
+
export declare const OAUTH_SCOPES: readonly ["account:read", "assets:read", "boards:read", "boards:write", "departments:read", "departments:write", "docs:read", "docs:write", "me:read", "notifications:write", "tags:read", "teams:read", "teams:write", "updates:read", "updates:write", "users:read", "users:write", "webhooks:read", "webhooks:write", "workspaces:read", "workspaces:write"];
|
|
91
|
+
export type OAuthScope = (typeof OAUTH_SCOPES)[number];
|
|
92
|
+
/**
|
|
93
|
+
* The default scope set requested by `monday auth login` — a working
|
|
94
|
+
* subset of {@link OAUTH_SCOPES}. Agents calling `monday auth login`
|
|
95
|
+
* without a `--scopes` flag (v0.4+) pick up these.
|
|
96
|
+
*/
|
|
97
|
+
export declare const OAUTH_DEFAULT_REQUESTED_SCOPES: readonly OAuthScope[];
|
|
98
|
+
/**
|
|
99
|
+
* The redirect payload as parsed by the listener.
|
|
100
|
+
*/
|
|
101
|
+
export type RedirectPayload = {
|
|
102
|
+
readonly kind: 'code';
|
|
103
|
+
readonly code: string;
|
|
104
|
+
readonly state: string;
|
|
105
|
+
} | {
|
|
106
|
+
readonly kind: 'error';
|
|
107
|
+
readonly error: string;
|
|
108
|
+
readonly errorDescription: string | undefined;
|
|
109
|
+
readonly state: string;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Inputs to {@link bindOAuthListener}. Both fields optional with
|
|
113
|
+
* pinned defaults.
|
|
114
|
+
*/
|
|
115
|
+
export interface BindOAuthListenerInputs {
|
|
116
|
+
readonly port?: number;
|
|
117
|
+
readonly timeoutMs?: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Handle returned from {@link bindOAuthListener}. Decoupled from
|
|
121
|
+
* `node:http`'s `Server` so tests can substitute a fixture handle
|
|
122
|
+
* without a real socket bind.
|
|
123
|
+
*/
|
|
124
|
+
export interface OAuthListenerHandle {
|
|
125
|
+
readonly port: number;
|
|
126
|
+
readonly awaitRedirect: () => Promise<RedirectPayload>;
|
|
127
|
+
readonly close: () => void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Inputs to {@link exchangeCode}. Mirror Monday's documented
|
|
131
|
+
* `/oauth2/token` body shape verbatim. `clientSecret` is **required**
|
|
132
|
+
* per the empirical probe; PKCE-only is not supported.
|
|
133
|
+
*/
|
|
134
|
+
export interface ExchangeCodeInputs {
|
|
135
|
+
readonly code: string;
|
|
136
|
+
readonly redirectUri: string;
|
|
137
|
+
readonly clientId: string;
|
|
138
|
+
readonly clientSecret: string;
|
|
139
|
+
/** Optional fetch-impl override for tests. */
|
|
140
|
+
readonly fetchImpl?: typeof fetch;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Raw `/oauth2/token` success-response body shape per Monday Apps
|
|
144
|
+
* OAuth docs.
|
|
145
|
+
*/
|
|
146
|
+
export interface RawTokenResponse {
|
|
147
|
+
readonly access_token: string;
|
|
148
|
+
readonly token_type: string;
|
|
149
|
+
readonly scope: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Normalized success-response shape that {@link exchangeCode} returns.
|
|
153
|
+
*/
|
|
154
|
+
export interface TokenResponse {
|
|
155
|
+
readonly accessToken: string;
|
|
156
|
+
readonly tokenType: string;
|
|
157
|
+
readonly scope: string;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Generates a 32-byte cryptographically-random `state` token, encoded
|
|
161
|
+
* base64url. Pure helper — no I/O.
|
|
162
|
+
*/
|
|
163
|
+
export declare const generateOAuthState: () => string;
|
|
164
|
+
/**
|
|
165
|
+
* Constant-time CSRF comparison. Returns `false` on length mismatch
|
|
166
|
+
* (without throwing — cli-design §7.3.1 step 5 routes that to
|
|
167
|
+
* `csrf_mismatch`, NOT `internal_error`). Returns `false` on the
|
|
168
|
+
* empty-string case.
|
|
169
|
+
*/
|
|
170
|
+
export declare const verifyCsrf: (received: string, expected: string) => boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Binds an HTTP listener on `127.0.0.1:<port>`, waits for a single
|
|
173
|
+
* redirect to `${OAUTH_CALLBACK_PATH}?code=…&state=…` (or
|
|
174
|
+
* `?error=…&state=…`), and returns a handle whose `awaitRedirect`
|
|
175
|
+
* resolves with the parsed payload.
|
|
176
|
+
*
|
|
177
|
+
* Failure surfaces:
|
|
178
|
+
* - Bind error (port held by another process or peer
|
|
179
|
+
* `monday auth login`) → reject with `oauth_failed.reason:
|
|
180
|
+
* "port_in_use"`.
|
|
181
|
+
* - 5-minute timer elapses with no redirect → reject with
|
|
182
|
+
* `oauth_failed.reason: "timeout"` (retryable: true; mirrors
|
|
183
|
+
* M2-era cache_error override-at-throw-site precedent).
|
|
184
|
+
*/
|
|
185
|
+
export declare const bindOAuthListener: (inputs?: BindOAuthListenerInputs) => Promise<OAuthListenerHandle>;
|
|
186
|
+
/**
|
|
187
|
+
* Posts the authorization code to `OAUTH_TOKEN_URL` and returns the
|
|
188
|
+
* normalized {@link TokenResponse}.
|
|
189
|
+
*
|
|
190
|
+
* Failure surfaces:
|
|
191
|
+
* - 4xx (RFC 6749 standard shape) → throws
|
|
192
|
+
* `oauth_failed.reason: "code_exchange_failed"` carrying
|
|
193
|
+
* `monday_code` + `monday_description`.
|
|
194
|
+
* - 5xx / network error → throws `network_error`.
|
|
195
|
+
* - Malformed success body → throws `internal_error`.
|
|
196
|
+
*/
|
|
197
|
+
export declare const exchangeCode: (inputs: ExchangeCodeInputs) => Promise<TokenResponse>;
|
|
198
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/api/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAQH,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,6CAA6C,CAAC;AAE9E,iDAAiD;AACjD,eAAO,MAAM,eAAe,yCAAyC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,sEAAsE;AACtE,eAAO,MAAM,iCAAiC,QAAgB,CAAC;AAE/D;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AAEtE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,EACH,MAAM,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,iWAsBf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS,UAAU,EAS/D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxE;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAqBD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAErC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,EAAE,UAAU,MAAM,KAAG,OAU/D,CAAC;AAOF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAQ,uBAA4B,KACnC,OAAO,CAAC,mBAAmB,CA0M7B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,kBAAkB,KACzB,OAAO,CAAC,aAAa,CAqHvB,CAAC"}
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth flow primitives for the v0.3-M21 `monday auth login` /
|
|
3
|
+
* `monday auth logout` verbs (cli-design §7.3 / §7.4).
|
|
4
|
+
*
|
|
5
|
+
* **Empirical probe findings (2026-05-10, against `auth.monday.com`):**
|
|
6
|
+
*
|
|
7
|
+
* - `/oauth2/authorize` accepts arbitrary query params and encodes
|
|
8
|
+
* them all into a JWT-signed `oauth_payload_token`, then 302-
|
|
9
|
+
* redirects to `https://auth.monday.com/login?oauth_payload_token=<jwt>`.
|
|
10
|
+
* Extra params like `code_challenge` + `code_challenge_method=S256`
|
|
11
|
+
* are silently round-tripped through the JWT but **not enforced**
|
|
12
|
+
* at token-exchange time — Monday's `/oauth2/token` requires
|
|
13
|
+
* `client_secret` regardless. Verbatim probe response when the
|
|
14
|
+
* PKCE-shape exchange omits `client_secret`:
|
|
15
|
+
* `{"error":"invalid_request","error_description":"Missing client_secret param"}`
|
|
16
|
+
* (status 400). PKCE is therefore **not load-bearing for v0.3**;
|
|
17
|
+
* the design ships without `code_challenge` / `code_verifier`.
|
|
18
|
+
*
|
|
19
|
+
* - `/oauth2/token` rejection responses follow RFC 6749 standard
|
|
20
|
+
* shape (status 400, `application/json; charset=utf-8`):
|
|
21
|
+
* `{"error": "<code>", "error_description": "<text>"}`.
|
|
22
|
+
*
|
|
23
|
+
* - Redirect URI matching is documented as exact (Monday Apps
|
|
24
|
+
* OAuth docs); design ships fixed-port `127.0.0.1:9876`.
|
|
25
|
+
*
|
|
26
|
+
* - Token response shape per Monday's docs:
|
|
27
|
+
* `{access_token, token_type, scope}`. **No `expires_in`**;
|
|
28
|
+
* Monday tokens "do not expire and are valid until the user
|
|
29
|
+
* uninstalls your app".
|
|
30
|
+
*
|
|
31
|
+
* **OAuth client registration (M21 implementation Part 1).**
|
|
32
|
+
* `OAUTH_CLIENT_ID` + `OAUTH_CLIENT_SECRET` are pinned in source
|
|
33
|
+
* per the public-OAuth-client convention — the secret authenticates
|
|
34
|
+
* the *app* (monday-cli), not the user. The user's flow is
|
|
35
|
+
* protected by the per-attempt `state` CSRF token + the listener-
|
|
36
|
+
* bound `redirect_uri`. **Until an OAuth app is registered with
|
|
37
|
+
* Monday's developer portal, the constants below carry placeholder
|
|
38
|
+
* values; production users see `oauth_failed.reason:
|
|
39
|
+
* "code_exchange_failed"` until they're swapped pre-publish.**
|
|
40
|
+
*/
|
|
41
|
+
import { randomBytes, timingSafeEqual } from 'node:crypto';
|
|
42
|
+
import { createServer } from 'node:http';
|
|
43
|
+
import { ApiError, errorMessage } from '../utils/errors.js';
|
|
44
|
+
import { unwrapOrThrow } from '../utils/parse-boundary.js';
|
|
45
|
+
import { z } from 'zod';
|
|
46
|
+
/** Monday Apps OAuth authorize endpoint. */
|
|
47
|
+
export const OAUTH_AUTHORIZE_URL = 'https://auth.monday.com/oauth2/authorize';
|
|
48
|
+
/** Monday Apps OAuth token-exchange endpoint. */
|
|
49
|
+
export const OAUTH_TOKEN_URL = 'https://auth.monday.com/oauth2/token';
|
|
50
|
+
/**
|
|
51
|
+
* Default port for the local-loopback OAuth callback listener. Pinned
|
|
52
|
+
* to `9876` to match cli-design §7.3.1 step 2; the OAuth app's
|
|
53
|
+
* redirect URI configuration pins this port.
|
|
54
|
+
*/
|
|
55
|
+
export const OAUTH_DEFAULT_PORT = 9876;
|
|
56
|
+
/** Path the listener answers; the OAuth app's redirect URI pins this. */
|
|
57
|
+
export const OAUTH_CALLBACK_PATH = '/callback';
|
|
58
|
+
/** Default listener timeout: 5 minutes (cli-design §7.3.1 step 4). */
|
|
59
|
+
export const OAUTH_DEFAULT_LISTENER_TIMEOUT_MS = 5 * 60 * 1000;
|
|
60
|
+
/**
|
|
61
|
+
* **PLACEHOLDER — replace with the registered Monday OAuth app's
|
|
62
|
+
* client_id pre-publish.** Tests do not depend on the value
|
|
63
|
+
* (cassettes intercept `/oauth2/token`); production users hit
|
|
64
|
+
* `oauth_failed.reason: "code_exchange_failed"` until swapped.
|
|
65
|
+
*
|
|
66
|
+
* Register at https://developer.monday.com/apps with redirect URI
|
|
67
|
+
* exactly `http://127.0.0.1:9876/callback`.
|
|
68
|
+
*/
|
|
69
|
+
export const OAUTH_CLIENT_ID = '<UNREGISTERED_PENDING_OAUTH_APP>';
|
|
70
|
+
/**
|
|
71
|
+
* **PLACEHOLDER — replace alongside {@link OAUTH_CLIENT_ID}.** Same
|
|
72
|
+
* pre-publish swap; see {@link OAUTH_CLIENT_ID} for context.
|
|
73
|
+
*/
|
|
74
|
+
export const OAUTH_CLIENT_SECRET = '<UNREGISTERED_PENDING_OAUTH_APP>';
|
|
75
|
+
/**
|
|
76
|
+
* Sentinel value the placeholder constants ship as until a Monday
|
|
77
|
+
* OAuth app is registered (see {@link OAUTH_CLIENT_ID} docstring).
|
|
78
|
+
* Exposed as a deliberately-widened `string` so consumers can compare
|
|
79
|
+
* `OAUTH_CLIENT_ID === OAUTH_UNREGISTERED_PLACEHOLDER` without
|
|
80
|
+
* triggering `@typescript-eslint/no-unnecessary-condition` on
|
|
81
|
+
* literal-vs-literal equality. v0.3-plan §8 Decision 11 rejected the
|
|
82
|
+
* v0.3 OAuth swap; the placeholder + guard in
|
|
83
|
+
* `src/commands/auth/login.ts` together surface a clear `usage_error`
|
|
84
|
+
* pointing users at `MONDAY_API_TOKEN` until a future version
|
|
85
|
+
* revisits the OAuth path.
|
|
86
|
+
*/
|
|
87
|
+
export const OAUTH_UNREGISTERED_PLACEHOLDER = '<UNREGISTERED_PENDING_OAUTH_APP>';
|
|
88
|
+
/**
|
|
89
|
+
* Documented Monday Apps OAuth scopes per Monday's published docs at
|
|
90
|
+
* the M21 pre-flight probe (2026-05-10). Each entry is exposed
|
|
91
|
+
* verbatim so the OAuth-app-registration step (M21 implementation
|
|
92
|
+
* Part 1) can request the subset the CLI actually needs without a
|
|
93
|
+
* second source-of-truth elsewhere.
|
|
94
|
+
*/
|
|
95
|
+
export const OAUTH_SCOPES = [
|
|
96
|
+
'account:read',
|
|
97
|
+
'assets:read',
|
|
98
|
+
'boards:read',
|
|
99
|
+
'boards:write',
|
|
100
|
+
'departments:read',
|
|
101
|
+
'departments:write',
|
|
102
|
+
'docs:read',
|
|
103
|
+
'docs:write',
|
|
104
|
+
'me:read',
|
|
105
|
+
'notifications:write',
|
|
106
|
+
'tags:read',
|
|
107
|
+
'teams:read',
|
|
108
|
+
'teams:write',
|
|
109
|
+
'updates:read',
|
|
110
|
+
'updates:write',
|
|
111
|
+
'users:read',
|
|
112
|
+
'users:write',
|
|
113
|
+
'webhooks:read',
|
|
114
|
+
'webhooks:write',
|
|
115
|
+
'workspaces:read',
|
|
116
|
+
'workspaces:write',
|
|
117
|
+
];
|
|
118
|
+
/**
|
|
119
|
+
* The default scope set requested by `monday auth login` — a working
|
|
120
|
+
* subset of {@link OAUTH_SCOPES}. Agents calling `monday auth login`
|
|
121
|
+
* without a `--scopes` flag (v0.4+) pick up these.
|
|
122
|
+
*/
|
|
123
|
+
export const OAUTH_DEFAULT_REQUESTED_SCOPES = [
|
|
124
|
+
'account:read',
|
|
125
|
+
'boards:read',
|
|
126
|
+
'boards:write',
|
|
127
|
+
'me:read',
|
|
128
|
+
'tags:read',
|
|
129
|
+
'updates:read',
|
|
130
|
+
'updates:write',
|
|
131
|
+
'users:read',
|
|
132
|
+
];
|
|
133
|
+
// `.loose()` so a Monday-side extension field (e.g., `expires_in` if
|
|
134
|
+
// Monday ever adds it) doesn't fail the parse. Forward-compatible
|
|
135
|
+
// widening: a field added by Monday lands in a Part 2+ amendment that
|
|
136
|
+
// surfaces it.
|
|
137
|
+
const rawTokenResponseSchema = z
|
|
138
|
+
.object({
|
|
139
|
+
access_token: z.string().min(1),
|
|
140
|
+
token_type: z.string().min(1),
|
|
141
|
+
scope: z.string(),
|
|
142
|
+
})
|
|
143
|
+
.loose();
|
|
144
|
+
const rfc6749ErrorSchema = z
|
|
145
|
+
.object({
|
|
146
|
+
error: z.string().min(1),
|
|
147
|
+
error_description: z.string().optional(),
|
|
148
|
+
})
|
|
149
|
+
.loose();
|
|
150
|
+
/**
|
|
151
|
+
* Generates a 32-byte cryptographically-random `state` token, encoded
|
|
152
|
+
* base64url. Pure helper — no I/O.
|
|
153
|
+
*/
|
|
154
|
+
export const generateOAuthState = () => {
|
|
155
|
+
return randomBytes(32).toString('base64url');
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Constant-time CSRF comparison. Returns `false` on length mismatch
|
|
159
|
+
* (without throwing — cli-design §7.3.1 step 5 routes that to
|
|
160
|
+
* `csrf_mismatch`, NOT `internal_error`). Returns `false` on the
|
|
161
|
+
* empty-string case.
|
|
162
|
+
*/
|
|
163
|
+
export const verifyCsrf = (received, expected) => {
|
|
164
|
+
const receivedBytes = Buffer.from(received, 'utf8');
|
|
165
|
+
const expectedBytes = Buffer.from(expected, 'utf8');
|
|
166
|
+
if (receivedBytes.length !== expectedBytes.length) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (receivedBytes.length === 0) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return timingSafeEqual(receivedBytes, expectedBytes);
|
|
173
|
+
};
|
|
174
|
+
const STATIC_SUCCESS_HTML = '<!DOCTYPE html><html><head><meta charset="utf-8"><title>monday-cli</title>' +
|
|
175
|
+
'<style>body{font-family:system-ui,sans-serif;max-width:480px;margin:64px auto;padding:0 16px;color:#1f2d3d;}</style>' +
|
|
176
|
+
'</head><body><h1>monday-cli</h1><p>You can close this tab now.</p></body></html>';
|
|
177
|
+
/**
|
|
178
|
+
* Binds an HTTP listener on `127.0.0.1:<port>`, waits for a single
|
|
179
|
+
* redirect to `${OAUTH_CALLBACK_PATH}?code=…&state=…` (or
|
|
180
|
+
* `?error=…&state=…`), and returns a handle whose `awaitRedirect`
|
|
181
|
+
* resolves with the parsed payload.
|
|
182
|
+
*
|
|
183
|
+
* Failure surfaces:
|
|
184
|
+
* - Bind error (port held by another process or peer
|
|
185
|
+
* `monday auth login`) → reject with `oauth_failed.reason:
|
|
186
|
+
* "port_in_use"`.
|
|
187
|
+
* - 5-minute timer elapses with no redirect → reject with
|
|
188
|
+
* `oauth_failed.reason: "timeout"` (retryable: true; mirrors
|
|
189
|
+
* M2-era cache_error override-at-throw-site precedent).
|
|
190
|
+
*/
|
|
191
|
+
export const bindOAuthListener = (inputs = {}) => {
|
|
192
|
+
const requestedPort = inputs.port ?? OAUTH_DEFAULT_PORT;
|
|
193
|
+
const timeoutMs = inputs.timeoutMs ?? OAUTH_DEFAULT_LISTENER_TIMEOUT_MS;
|
|
194
|
+
return new Promise((resolveBind, rejectBind) => {
|
|
195
|
+
let pendingPayload;
|
|
196
|
+
let redirectResolver;
|
|
197
|
+
let closed = false;
|
|
198
|
+
const server = createServer((req, res) => {
|
|
199
|
+
const url = req.url ?? '/';
|
|
200
|
+
const parsed = (() => {
|
|
201
|
+
try {
|
|
202
|
+
return new URL(url, `http://127.0.0.1`);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// Defensive: a malformed URL string from Node's http parser is
|
|
206
|
+
// vanishingly rare; the catch guard keeps the listener loud
|
|
207
|
+
// rather than crashing.
|
|
208
|
+
/* c8 ignore next */
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
})();
|
|
212
|
+
if (parsed?.pathname !== OAUTH_CALLBACK_PATH) {
|
|
213
|
+
res.statusCode = 404;
|
|
214
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
215
|
+
res.end('not found');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const params = parsed.searchParams;
|
|
219
|
+
const state = params.get('state') ?? '';
|
|
220
|
+
const code = params.get('code');
|
|
221
|
+
const errorParam = params.get('error');
|
|
222
|
+
if (errorParam !== null && errorParam.length > 0) {
|
|
223
|
+
res.statusCode = 200;
|
|
224
|
+
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
225
|
+
res.end(STATIC_SUCCESS_HTML);
|
|
226
|
+
const errorDescription = params.get('error_description') ?? undefined;
|
|
227
|
+
const payload = {
|
|
228
|
+
kind: 'error',
|
|
229
|
+
error: errorParam,
|
|
230
|
+
errorDescription,
|
|
231
|
+
state,
|
|
232
|
+
};
|
|
233
|
+
// Race-window guard; production callers always subscribe
|
|
234
|
+
// before the redirect arrives.
|
|
235
|
+
/* c8 ignore start */
|
|
236
|
+
if (redirectResolver !== undefined) {
|
|
237
|
+
redirectResolver(payload);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
pendingPayload = payload;
|
|
241
|
+
}
|
|
242
|
+
/* c8 ignore stop */
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (code !== null && code.length > 0) {
|
|
246
|
+
res.statusCode = 200;
|
|
247
|
+
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
248
|
+
res.end(STATIC_SUCCESS_HTML);
|
|
249
|
+
const payload = { kind: 'code', code, state };
|
|
250
|
+
// Race-window guard; production callers always subscribe
|
|
251
|
+
// before the redirect arrives.
|
|
252
|
+
/* c8 ignore start */
|
|
253
|
+
if (redirectResolver !== undefined) {
|
|
254
|
+
redirectResolver(payload);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
pendingPayload = payload;
|
|
258
|
+
}
|
|
259
|
+
/* c8 ignore stop */
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
// Defensive: neither `code` nor `error` is unreachable via
|
|
263
|
+
// Monday's redirect (always populates one). The 400 keeps the
|
|
264
|
+
// listener loud rather than hanging on a malformed URL.
|
|
265
|
+
res.statusCode = 400;
|
|
266
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
267
|
+
res.end('missing code or error parameter');
|
|
268
|
+
});
|
|
269
|
+
const closeServer = () => {
|
|
270
|
+
// closeServer is idempotent; the guard fires only when both
|
|
271
|
+
// the redirect handler and the timeout race to close, which
|
|
272
|
+
// tests don't reproduce deterministically.
|
|
273
|
+
/* c8 ignore start */
|
|
274
|
+
if (closed) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
/* c8 ignore stop */
|
|
278
|
+
closed = true;
|
|
279
|
+
// Best-effort close — `Server.close()` waits for connections to
|
|
280
|
+
// drain. The static HTML page closes immediately after `res.end`,
|
|
281
|
+
// so this completes promptly in the happy path.
|
|
282
|
+
server.close(() => {
|
|
283
|
+
// c8 ignore next — close callback completes after connections drain.
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
server.once('error', (err) => {
|
|
287
|
+
if (err.code === 'EADDRINUSE') {
|
|
288
|
+
rejectBind(new ApiError('oauth_failed', `local OAuth listener cannot bind 127.0.0.1:${String(requestedPort)} — port already in use`, {
|
|
289
|
+
details: {
|
|
290
|
+
reason: 'port_in_use',
|
|
291
|
+
port: requestedPort,
|
|
292
|
+
hint: 'another `monday auth login` process or unrelated service is holding the port; resolve the conflict and retry',
|
|
293
|
+
},
|
|
294
|
+
cause: err,
|
|
295
|
+
}));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// Non-EADDRINUSE bind errors are rare (EACCES on privileged
|
|
299
|
+
// ports, ENOMEM, etc.) and not reproducible from a unit test
|
|
300
|
+
// against 127.0.0.1:0.
|
|
301
|
+
/* c8 ignore start */
|
|
302
|
+
rejectBind(new ApiError('oauth_failed', `local OAuth listener failed to bind 127.0.0.1:${String(requestedPort)}: ${err.message}`, {
|
|
303
|
+
details: { reason: 'port_in_use', port: requestedPort },
|
|
304
|
+
cause: err,
|
|
305
|
+
}));
|
|
306
|
+
/* c8 ignore stop */
|
|
307
|
+
});
|
|
308
|
+
server.listen(requestedPort, '127.0.0.1', () => {
|
|
309
|
+
// Resolve the actual bound port — when caller passed `0`, the
|
|
310
|
+
// OS assigned a random free port; tests + the consent URL need
|
|
311
|
+
// the real one. The non-object/null address branch covers Unix-
|
|
312
|
+
// socket binds that this 127.0.0.1 listener never produces.
|
|
313
|
+
const address = server.address();
|
|
314
|
+
/* c8 ignore start */
|
|
315
|
+
const actualPort = typeof address === 'object' && address !== null
|
|
316
|
+
? address.port
|
|
317
|
+
: requestedPort;
|
|
318
|
+
/* c8 ignore stop */
|
|
319
|
+
const handle = {
|
|
320
|
+
port: actualPort,
|
|
321
|
+
awaitRedirect: () => new Promise((resolve, reject) => {
|
|
322
|
+
// If the redirect arrived before awaitRedirect was called
|
|
323
|
+
// (vanishingly rare in production but possible in fast
|
|
324
|
+
// test paths), drain the pending payload immediately.
|
|
325
|
+
/* c8 ignore next 6 — race-window guard; unit tests subscribe
|
|
326
|
+
before sending the redirect, so this path doesn't fire. */
|
|
327
|
+
if (pendingPayload !== undefined) {
|
|
328
|
+
const p = pendingPayload;
|
|
329
|
+
pendingPayload = undefined;
|
|
330
|
+
closeServer();
|
|
331
|
+
resolve(p);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
// Arm the timer here, not at bind time — the 5-min budget
|
|
335
|
+
// is "wait for redirect" not "wait for caller to subscribe."
|
|
336
|
+
const timer = setTimeout(() => {
|
|
337
|
+
const err = new ApiError('oauth_failed', `OAuth listener timed out after ${String(timeoutMs)}ms waiting for the redirect`, {
|
|
338
|
+
details: {
|
|
339
|
+
reason: 'timeout',
|
|
340
|
+
timeout_ms: timeoutMs,
|
|
341
|
+
hint: 're-run `monday auth login` and complete the consent flow within 5 minutes',
|
|
342
|
+
},
|
|
343
|
+
// Override the umbrella `oauth_failed` retryable=false
|
|
344
|
+
// floor — listener-timeout is a transient signal an
|
|
345
|
+
// agent can safely retry (cli-design §7.3.3 footnote).
|
|
346
|
+
retryable: true,
|
|
347
|
+
});
|
|
348
|
+
closeServer();
|
|
349
|
+
reject(err);
|
|
350
|
+
}, timeoutMs);
|
|
351
|
+
timer.unref();
|
|
352
|
+
redirectResolver = (payload) => {
|
|
353
|
+
clearTimeout(timer);
|
|
354
|
+
closeServer();
|
|
355
|
+
resolve(payload);
|
|
356
|
+
};
|
|
357
|
+
}),
|
|
358
|
+
close: closeServer,
|
|
359
|
+
};
|
|
360
|
+
resolveBind(handle);
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* Posts the authorization code to `OAUTH_TOKEN_URL` and returns the
|
|
366
|
+
* normalized {@link TokenResponse}.
|
|
367
|
+
*
|
|
368
|
+
* Failure surfaces:
|
|
369
|
+
* - 4xx (RFC 6749 standard shape) → throws
|
|
370
|
+
* `oauth_failed.reason: "code_exchange_failed"` carrying
|
|
371
|
+
* `monday_code` + `monday_description`.
|
|
372
|
+
* - 5xx / network error → throws `network_error`.
|
|
373
|
+
* - Malformed success body → throws `internal_error`.
|
|
374
|
+
*/
|
|
375
|
+
export const exchangeCode = async (inputs) => {
|
|
376
|
+
const body = new URLSearchParams({
|
|
377
|
+
grant_type: 'authorization_code',
|
|
378
|
+
code: inputs.code,
|
|
379
|
+
client_id: inputs.clientId,
|
|
380
|
+
client_secret: inputs.clientSecret,
|
|
381
|
+
redirect_uri: inputs.redirectUri,
|
|
382
|
+
}).toString();
|
|
383
|
+
const fetchImpl = inputs.fetchImpl ?? fetch;
|
|
384
|
+
let response;
|
|
385
|
+
try {
|
|
386
|
+
response = await fetchImpl(OAUTH_TOKEN_URL, {
|
|
387
|
+
method: 'POST',
|
|
388
|
+
headers: {
|
|
389
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
390
|
+
accept: 'application/json',
|
|
391
|
+
},
|
|
392
|
+
body,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
catch (err) {
|
|
396
|
+
throw new ApiError('network_error', `network failure during OAuth token exchange: ${errorMessage(err)}`, {
|
|
397
|
+
cause: err,
|
|
398
|
+
details: {
|
|
399
|
+
url: OAUTH_TOKEN_URL,
|
|
400
|
+
hint: 'verify connectivity to auth.monday.com and retry',
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const responseBodyText = await response.text();
|
|
405
|
+
if (response.status >= 200 && response.status < 300) {
|
|
406
|
+
let parsedJson;
|
|
407
|
+
try {
|
|
408
|
+
parsedJson = JSON.parse(responseBodyText);
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
throw new ApiError('internal_error', `OAuth token-exchange success response was not valid JSON (status ${String(response.status)})`, {
|
|
412
|
+
cause: err,
|
|
413
|
+
details: {
|
|
414
|
+
http_status: response.status,
|
|
415
|
+
hint: 'this likely indicates a Monday-side change in the response shape; inspect the live response and report.',
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
// R-NEW-19 lift — canonical parse-failure via `unwrapOrThrow`;
|
|
420
|
+
// `details.http_status` threads through as a per-call discriminant.
|
|
421
|
+
const tokenResponse = unwrapOrThrow(rawTokenResponseSchema.safeParse(parsedJson), {
|
|
422
|
+
context: 'OAuth token-exchange success response',
|
|
423
|
+
details: { http_status: response.status },
|
|
424
|
+
hint: 'this likely indicates a Monday-side change in the response shape; inspect the live response and report.',
|
|
425
|
+
});
|
|
426
|
+
return {
|
|
427
|
+
accessToken: tokenResponse.access_token,
|
|
428
|
+
tokenType: tokenResponse.token_type,
|
|
429
|
+
scope: tokenResponse.scope,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (response.status >= 400 && response.status < 500) {
|
|
433
|
+
let mondayCode;
|
|
434
|
+
let mondayDescription;
|
|
435
|
+
try {
|
|
436
|
+
const parsedJson = JSON.parse(responseBodyText);
|
|
437
|
+
const result = rfc6749ErrorSchema.safeParse(parsedJson);
|
|
438
|
+
if (result.success) {
|
|
439
|
+
mondayCode = result.data.error;
|
|
440
|
+
mondayDescription = result.data.error_description;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
// Body wasn't JSON — leave mondayCode undefined and let the
|
|
445
|
+
// throw below carry the raw status.
|
|
446
|
+
}
|
|
447
|
+
throw new ApiError('oauth_failed', `OAuth token exchange failed with HTTP ${String(response.status)}${mondayCode !== undefined ? ` (${mondayCode})` : ''}`, {
|
|
448
|
+
httpStatus: response.status,
|
|
449
|
+
...(mondayCode !== undefined ? { mondayCode } : {}),
|
|
450
|
+
details: {
|
|
451
|
+
reason: 'code_exchange_failed',
|
|
452
|
+
http_status: response.status,
|
|
453
|
+
...(mondayCode !== undefined ? { monday_code: mondayCode } : {}),
|
|
454
|
+
...(mondayDescription !== undefined
|
|
455
|
+
? { monday_description: mondayDescription }
|
|
456
|
+
: {}),
|
|
457
|
+
hint: 're-run `monday auth login --profile <name>` to start a fresh OAuth flow',
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
// 5xx or anything else: treat as transient transport-level failure.
|
|
462
|
+
throw new ApiError('network_error', `OAuth token exchange failed with HTTP ${String(response.status)}`, {
|
|
463
|
+
httpStatus: response.status,
|
|
464
|
+
details: {
|
|
465
|
+
url: OAUTH_TOKEN_URL,
|
|
466
|
+
http_status: response.status,
|
|
467
|
+
hint: 'transient server-side failure; retry shortly',
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
};
|
|
471
|
+
//# sourceMappingURL=oauth.js.map
|