monday-cli 0.2.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 +439 -0
- package/LICENSE +21 -0
- package/README.md +431 -0
- package/dist/api/board-child-finder.d.ts +95 -0
- package/dist/api/board-child-finder.d.ts.map +1 -0
- package/dist/api/board-child-finder.js +89 -0
- package/dist/api/board-child-finder.js.map +1 -0
- package/dist/api/board-metadata.d.ts +162 -0
- package/dist/api/board-metadata.d.ts.map +1 -0
- package/dist/api/board-metadata.js +238 -0
- package/dist/api/board-metadata.js.map +1 -0
- package/dist/api/board-mutation-invalidation.d.ts +153 -0
- package/dist/api/board-mutation-invalidation.d.ts.map +1 -0
- package/dist/api/board-mutation-invalidation.js +136 -0
- package/dist/api/board-mutation-invalidation.js.map +1 -0
- package/dist/api/board-mutation-result.d.ts +97 -0
- package/dist/api/board-mutation-result.d.ts.map +1 -0
- package/dist/api/board-mutation-result.js +99 -0
- package/dist/api/board-mutation-result.js.map +1 -0
- package/dist/api/board-projection.d.ts +68 -0
- package/dist/api/board-projection.d.ts.map +1 -0
- package/dist/api/board-projection.js +79 -0
- package/dist/api/board-projection.js.map +1 -0
- package/dist/api/cache.d.ts +150 -0
- package/dist/api/cache.d.ts.map +1 -0
- package/dist/api/cache.js +418 -0
- package/dist/api/cache.js.map +1 -0
- package/dist/api/client.d.ts +162 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +205 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/column-mapping.d.ts +68 -0
- package/dist/api/column-mapping.d.ts.map +1 -0
- package/dist/api/column-mapping.js +117 -0
- package/dist/api/column-mapping.js.map +1 -0
- package/dist/api/column-mutation-result.d.ts +136 -0
- package/dist/api/column-mutation-result.d.ts.map +1 -0
- package/dist/api/column-mutation-result.js +130 -0
- package/dist/api/column-mutation-result.js.map +1 -0
- package/dist/api/column-types.d.ts +215 -0
- package/dist/api/column-types.d.ts.map +1 -0
- package/dist/api/column-types.js +195 -0
- package/dist/api/column-types.js.map +1 -0
- package/dist/api/column-values.d.ts +446 -0
- package/dist/api/column-values.d.ts.map +1 -0
- package/dist/api/column-values.js +795 -0
- package/dist/api/column-values.js.map +1 -0
- package/dist/api/columns.d.ts +205 -0
- package/dist/api/columns.d.ts.map +1 -0
- package/dist/api/columns.js +343 -0
- package/dist/api/columns.js.map +1 -0
- package/dist/api/complexity.d.ts +90 -0
- package/dist/api/complexity.d.ts.map +1 -0
- package/dist/api/complexity.js +194 -0
- package/dist/api/complexity.js.map +1 -0
- package/dist/api/dates.d.ts +150 -0
- package/dist/api/dates.d.ts.map +1 -0
- package/dist/api/dates.js +490 -0
- package/dist/api/dates.js.map +1 -0
- package/dist/api/destructive-gate.d.ts +107 -0
- package/dist/api/destructive-gate.d.ts.map +1 -0
- package/dist/api/destructive-gate.js +19 -0
- package/dist/api/destructive-gate.js.map +1 -0
- package/dist/api/dry-run.d.ts +338 -0
- package/dist/api/dry-run.d.ts.map +1 -0
- package/dist/api/dry-run.js +607 -0
- package/dist/api/dry-run.js.map +1 -0
- package/dist/api/emails.d.ts +60 -0
- package/dist/api/emails.d.ts.map +1 -0
- package/dist/api/emails.js +113 -0
- package/dist/api/emails.js.map +1 -0
- package/dist/api/errors.d.ts +82 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +434 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/filters.d.ts +198 -0
- package/dist/api/filters.d.ts.map +1 -0
- package/dist/api/filters.js +328 -0
- package/dist/api/filters.js.map +1 -0
- package/dist/api/group-color.d.ts +33 -0
- package/dist/api/group-color.d.ts.map +1 -0
- package/dist/api/group-color.js +80 -0
- package/dist/api/group-color.js.map +1 -0
- package/dist/api/group-mutation-result.d.ts +150 -0
- package/dist/api/group-mutation-result.d.ts.map +1 -0
- package/dist/api/group-mutation-result.js +141 -0
- package/dist/api/group-mutation-result.js.map +1 -0
- package/dist/api/iso-country-codes.d.ts +45 -0
- package/dist/api/iso-country-codes.d.ts.map +1 -0
- package/dist/api/iso-country-codes.js +71 -0
- package/dist/api/iso-country-codes.js.map +1 -0
- package/dist/api/item-board-lookup.d.ts +86 -0
- package/dist/api/item-board-lookup.d.ts.map +1 -0
- package/dist/api/item-board-lookup.js +140 -0
- package/dist/api/item-board-lookup.js.map +1 -0
- package/dist/api/item-helpers.d.ts +133 -0
- package/dist/api/item-helpers.d.ts.map +1 -0
- package/dist/api/item-helpers.js +139 -0
- package/dist/api/item-helpers.js.map +1 -0
- package/dist/api/item-mutation-result.d.ts +60 -0
- package/dist/api/item-mutation-result.d.ts.map +1 -0
- package/dist/api/item-mutation-result.js +63 -0
- package/dist/api/item-mutation-result.js.map +1 -0
- package/dist/api/item-projection.d.ts +165 -0
- package/dist/api/item-projection.d.ts.map +1 -0
- package/dist/api/item-projection.js +235 -0
- package/dist/api/item-projection.js.map +1 -0
- package/dist/api/item-source-read.d.ts +45 -0
- package/dist/api/item-source-read.d.ts.map +1 -0
- package/dist/api/item-source-read.js +57 -0
- package/dist/api/item-source-read.js.map +1 -0
- package/dist/api/items-page-walker.d.ts +126 -0
- package/dist/api/items-page-walker.d.ts.map +1 -0
- package/dist/api/items-page-walker.js +256 -0
- package/dist/api/items-page-walker.js.map +1 -0
- package/dist/api/links.d.ts +70 -0
- package/dist/api/links.d.ts.map +1 -0
- package/dist/api/links.js +128 -0
- package/dist/api/links.js.map +1 -0
- package/dist/api/me-token.d.ts +52 -0
- package/dist/api/me-token.d.ts.map +1 -0
- package/dist/api/me-token.js +55 -0
- package/dist/api/me-token.js.map +1 -0
- package/dist/api/pagination.d.ts +201 -0
- package/dist/api/pagination.d.ts.map +1 -0
- package/dist/api/pagination.js +223 -0
- package/dist/api/pagination.js.map +1 -0
- package/dist/api/partial-success-mutation.d.ts +28 -0
- package/dist/api/partial-success-mutation.d.ts.map +1 -0
- package/dist/api/partial-success-mutation.js +68 -0
- package/dist/api/partial-success-mutation.js.map +1 -0
- package/dist/api/people.d.ts +182 -0
- package/dist/api/people.d.ts.map +1 -0
- package/dist/api/people.js +260 -0
- package/dist/api/people.js.map +1 -0
- package/dist/api/phones.d.ts +74 -0
- package/dist/api/phones.d.ts.map +1 -0
- package/dist/api/phones.js +167 -0
- package/dist/api/phones.js.map +1 -0
- package/dist/api/raw-document.d.ts +53 -0
- package/dist/api/raw-document.d.ts.map +1 -0
- package/dist/api/raw-document.js +177 -0
- package/dist/api/raw-document.js.map +1 -0
- package/dist/api/raw-write.d.ts +127 -0
- package/dist/api/raw-write.d.ts.map +1 -0
- package/dist/api/raw-write.js +233 -0
- package/dist/api/raw-write.js.map +1 -0
- package/dist/api/resolution-context.d.ts +32 -0
- package/dist/api/resolution-context.d.ts.map +1 -0
- package/dist/api/resolution-context.js +42 -0
- package/dist/api/resolution-context.js.map +1 -0
- package/dist/api/resolution-pass.d.ts +163 -0
- package/dist/api/resolution-pass.d.ts.map +1 -0
- package/dist/api/resolution-pass.js +254 -0
- package/dist/api/resolution-pass.js.map +1 -0
- package/dist/api/resolve-client.d.ts +69 -0
- package/dist/api/resolve-client.d.ts.map +1 -0
- package/dist/api/resolve-client.js +70 -0
- package/dist/api/resolve-client.js.map +1 -0
- package/dist/api/resolver-error-fold.d.ts +176 -0
- package/dist/api/resolver-error-fold.d.ts.map +1 -0
- package/dist/api/resolver-error-fold.js +230 -0
- package/dist/api/resolver-error-fold.js.map +1 -0
- package/dist/api/resolvers.d.ts +131 -0
- package/dist/api/resolvers.d.ts.map +1 -0
- package/dist/api/resolvers.js +262 -0
- package/dist/api/resolvers.js.map +1 -0
- package/dist/api/response-root.d.ts +65 -0
- package/dist/api/response-root.d.ts.map +1 -0
- package/dist/api/response-root.js +61 -0
- package/dist/api/response-root.js.map +1 -0
- package/dist/api/retry.d.ts +112 -0
- package/dist/api/retry.d.ts.map +1 -0
- package/dist/api/retry.js +181 -0
- package/dist/api/retry.js.map +1 -0
- package/dist/api/set-expression.d.ts +23 -0
- package/dist/api/set-expression.d.ts.map +1 -0
- package/dist/api/set-expression.js +31 -0
- package/dist/api/set-expression.js.map +1 -0
- package/dist/api/sort.d.ts +59 -0
- package/dist/api/sort.d.ts.map +1 -0
- package/dist/api/sort.js +73 -0
- package/dist/api/sort.js.map +1 -0
- package/dist/api/source-aggregator.d.ts +94 -0
- package/dist/api/source-aggregator.d.ts.map +1 -0
- package/dist/api/source-aggregator.js +111 -0
- package/dist/api/source-aggregator.js.map +1 -0
- package/dist/api/transport.d.ts +58 -0
- package/dist/api/transport.d.ts.map +1 -0
- package/dist/api/transport.js +190 -0
- package/dist/api/transport.js.map +1 -0
- package/dist/api/update-mutation-result.d.ts +133 -0
- package/dist/api/update-mutation-result.d.ts.map +1 -0
- package/dist/api/update-mutation-result.js +145 -0
- package/dist/api/update-mutation-result.js.map +1 -0
- package/dist/api/users-fan-out-mutation.d.ts +124 -0
- package/dist/api/users-fan-out-mutation.d.ts.map +1 -0
- package/dist/api/users-fan-out-mutation.js +331 -0
- package/dist/api/users-fan-out-mutation.js.map +1 -0
- package/dist/api/walk-pages.d.ts +91 -0
- package/dist/api/walk-pages.d.ts.map +1 -0
- package/dist/api/walk-pages.js +84 -0
- package/dist/api/walk-pages.js.map +1 -0
- package/dist/api/workspace-projection.d.ts +64 -0
- package/dist/api/workspace-projection.d.ts.map +1 -0
- package/dist/api/workspace-projection.js +83 -0
- package/dist/api/workspace-projection.js.map +1 -0
- package/dist/cli/envelope-out.d.ts +128 -0
- package/dist/cli/envelope-out.d.ts.map +1 -0
- package/dist/cli/envelope-out.js +146 -0
- package/dist/cli/envelope-out.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +27 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/program.d.ts +29 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +109 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/run.d.ts +108 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +105 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/commands/account/client-helper.d.ts +37 -0
- package/dist/commands/account/client-helper.d.ts.map +1 -0
- package/dist/commands/account/client-helper.js +55 -0
- package/dist/commands/account/client-helper.js.map +1 -0
- package/dist/commands/account/complexity.d.ts +29 -0
- package/dist/commands/account/complexity.d.ts.map +1 -0
- package/dist/commands/account/complexity.js +70 -0
- package/dist/commands/account/complexity.js.map +1 -0
- package/dist/commands/account/info.d.ts +36 -0
- package/dist/commands/account/info.d.ts.map +1 -0
- package/dist/commands/account/info.js +74 -0
- package/dist/commands/account/info.js.map +1 -0
- package/dist/commands/account/version.d.ts +44 -0
- package/dist/commands/account/version.d.ts.map +1 -0
- package/dist/commands/account/version.js +98 -0
- package/dist/commands/account/version.js.map +1 -0
- package/dist/commands/account/whoami.d.ts +34 -0
- package/dist/commands/account/whoami.d.ts.map +1 -0
- package/dist/commands/account/whoami.js +77 -0
- package/dist/commands/account/whoami.js.map +1 -0
- package/dist/commands/board/add-users.d.ts +60 -0
- package/dist/commands/board/add-users.d.ts.map +1 -0
- package/dist/commands/board/add-users.js +133 -0
- package/dist/commands/board/add-users.js.map +1 -0
- package/dist/commands/board/archive.d.ts +64 -0
- package/dist/commands/board/archive.d.ts.map +1 -0
- package/dist/commands/board/archive.js +226 -0
- package/dist/commands/board/archive.js.map +1 -0
- package/dist/commands/board/column-create.d.ts +146 -0
- package/dist/commands/board/column-create.d.ts.map +1 -0
- package/dist/commands/board/column-create.js +564 -0
- package/dist/commands/board/column-create.js.map +1 -0
- package/dist/commands/board/column-delete.d.ts +76 -0
- package/dist/commands/board/column-delete.d.ts.map +1 -0
- package/dist/commands/board/column-delete.js +224 -0
- package/dist/commands/board/column-delete.js.map +1 -0
- package/dist/commands/board/column-update.d.ts +92 -0
- package/dist/commands/board/column-update.d.ts.map +1 -0
- package/dist/commands/board/column-update.js +364 -0
- package/dist/commands/board/column-update.js.map +1 -0
- package/dist/commands/board/columns.d.ts +30 -0
- package/dist/commands/board/columns.d.ts.map +1 -0
- package/dist/commands/board/columns.js +102 -0
- package/dist/commands/board/columns.js.map +1 -0
- package/dist/commands/board/create.d.ts +67 -0
- package/dist/commands/board/create.d.ts.map +1 -0
- package/dist/commands/board/create.js +226 -0
- package/dist/commands/board/create.js.map +1 -0
- package/dist/commands/board/delete.d.ts +60 -0
- package/dist/commands/board/delete.d.ts.map +1 -0
- package/dist/commands/board/delete.js +192 -0
- package/dist/commands/board/delete.js.map +1 -0
- package/dist/commands/board/describe.d.ts +68 -0
- package/dist/commands/board/describe.d.ts.map +1 -0
- package/dist/commands/board/describe.js +241 -0
- package/dist/commands/board/describe.js.map +1 -0
- package/dist/commands/board/doctor.d.ts +108 -0
- package/dist/commands/board/doctor.d.ts.map +1 -0
- package/dist/commands/board/doctor.js +417 -0
- package/dist/commands/board/doctor.js.map +1 -0
- package/dist/commands/board/duplicate.d.ts +85 -0
- package/dist/commands/board/duplicate.d.ts.map +1 -0
- package/dist/commands/board/duplicate.js +281 -0
- package/dist/commands/board/duplicate.js.map +1 -0
- package/dist/commands/board/find.d.ts +47 -0
- package/dist/commands/board/find.d.ts.map +1 -0
- package/dist/commands/board/find.js +153 -0
- package/dist/commands/board/find.js.map +1 -0
- package/dist/commands/board/get.d.ts +41 -0
- package/dist/commands/board/get.d.ts.map +1 -0
- package/dist/commands/board/get.js +66 -0
- package/dist/commands/board/get.js.map +1 -0
- package/dist/commands/board/group-archive.d.ts +83 -0
- package/dist/commands/board/group-archive.d.ts.map +1 -0
- package/dist/commands/board/group-archive.js +264 -0
- package/dist/commands/board/group-archive.js.map +1 -0
- package/dist/commands/board/group-create.d.ts +118 -0
- package/dist/commands/board/group-create.d.ts.map +1 -0
- package/dist/commands/board/group-create.js +239 -0
- package/dist/commands/board/group-create.js.map +1 -0
- package/dist/commands/board/group-delete.d.ts +79 -0
- package/dist/commands/board/group-delete.d.ts.map +1 -0
- package/dist/commands/board/group-delete.js +222 -0
- package/dist/commands/board/group-delete.js.map +1 -0
- package/dist/commands/board/group-duplicate.d.ts +70 -0
- package/dist/commands/board/group-duplicate.d.ts.map +1 -0
- package/dist/commands/board/group-duplicate.js +219 -0
- package/dist/commands/board/group-duplicate.js.map +1 -0
- package/dist/commands/board/group-update.d.ts +145 -0
- package/dist/commands/board/group-update.d.ts.map +1 -0
- package/dist/commands/board/group-update.js +341 -0
- package/dist/commands/board/group-update.js.map +1 -0
- package/dist/commands/board/groups.d.ts +28 -0
- package/dist/commands/board/groups.d.ts.map +1 -0
- package/dist/commands/board/groups.js +85 -0
- package/dist/commands/board/groups.js.map +1 -0
- package/dist/commands/board/list.d.ts +39 -0
- package/dist/commands/board/list.d.ts.map +1 -0
- package/dist/commands/board/list.js +135 -0
- package/dist/commands/board/list.js.map +1 -0
- package/dist/commands/board/subscribers.d.ts +24 -0
- package/dist/commands/board/subscribers.d.ts.map +1 -0
- package/dist/commands/board/subscribers.js +89 -0
- package/dist/commands/board/subscribers.js.map +1 -0
- package/dist/commands/board/update.d.ts +82 -0
- package/dist/commands/board/update.d.ts.map +1 -0
- package/dist/commands/board/update.js +328 -0
- package/dist/commands/board/update.js.map +1 -0
- package/dist/commands/cache/clear.d.ts +34 -0
- package/dist/commands/cache/clear.d.ts.map +1 -0
- package/dist/commands/cache/clear.js +113 -0
- package/dist/commands/cache/clear.js.map +1 -0
- package/dist/commands/cache/list.d.ts +50 -0
- package/dist/commands/cache/list.d.ts.map +1 -0
- package/dist/commands/cache/list.js +77 -0
- package/dist/commands/cache/list.js.map +1 -0
- package/dist/commands/cache/stats.d.ts +22 -0
- package/dist/commands/cache/stats.d.ts.map +1 -0
- package/dist/commands/cache/stats.js +56 -0
- package/dist/commands/cache/stats.js.map +1 -0
- package/dist/commands/config/path.d.ts +22 -0
- package/dist/commands/config/path.d.ts.map +1 -0
- package/dist/commands/config/path.js +74 -0
- package/dist/commands/config/path.js.map +1 -0
- package/dist/commands/config/show.d.ts +61 -0
- package/dist/commands/config/show.d.ts.map +1 -0
- package/dist/commands/config/show.js +137 -0
- package/dist/commands/config/show.js.map +1 -0
- package/dist/commands/emit.d.ts +156 -0
- package/dist/commands/emit.d.ts.map +1 -0
- package/dist/commands/emit.js +212 -0
- package/dist/commands/emit.js.map +1 -0
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +195 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/item/archive.d.ts +81 -0
- package/dist/commands/item/archive.d.ts.map +1 -0
- package/dist/commands/item/archive.js +187 -0
- package/dist/commands/item/archive.js.map +1 -0
- package/dist/commands/item/clear.d.ts +140 -0
- package/dist/commands/item/clear.d.ts.map +1 -0
- package/dist/commands/item/clear.js +748 -0
- package/dist/commands/item/clear.js.map +1 -0
- package/dist/commands/item/create.d.ts +77 -0
- package/dist/commands/item/create.d.ts.map +1 -0
- package/dist/commands/item/create.js +802 -0
- package/dist/commands/item/create.js.map +1 -0
- package/dist/commands/item/delete.d.ts +82 -0
- package/dist/commands/item/delete.d.ts.map +1 -0
- package/dist/commands/item/delete.js +179 -0
- package/dist/commands/item/delete.js.map +1 -0
- package/dist/commands/item/duplicate.d.ts +117 -0
- package/dist/commands/item/duplicate.d.ts.map +1 -0
- package/dist/commands/item/duplicate.js +238 -0
- package/dist/commands/item/duplicate.js.map +1 -0
- package/dist/commands/item/find.d.ts +55 -0
- package/dist/commands/item/find.d.ts.map +1 -0
- package/dist/commands/item/find.js +231 -0
- package/dist/commands/item/find.js.map +1 -0
- package/dist/commands/item/get.d.ts +47 -0
- package/dist/commands/item/get.d.ts.map +1 -0
- package/dist/commands/item/get.js +66 -0
- package/dist/commands/item/get.js.map +1 -0
- package/dist/commands/item/list.d.ts +73 -0
- package/dist/commands/item/list.d.ts.map +1 -0
- package/dist/commands/item/list.js +284 -0
- package/dist/commands/item/list.js.map +1 -0
- package/dist/commands/item/move.d.ts +181 -0
- package/dist/commands/item/move.d.ts.map +1 -0
- package/dist/commands/item/move.js +560 -0
- package/dist/commands/item/move.js.map +1 -0
- package/dist/commands/item/search.d.ts +67 -0
- package/dist/commands/item/search.d.ts.map +1 -0
- package/dist/commands/item/search.js +322 -0
- package/dist/commands/item/search.js.map +1 -0
- package/dist/commands/item/set.d.ts +88 -0
- package/dist/commands/item/set.d.ts.map +1 -0
- package/dist/commands/item/set.js +387 -0
- package/dist/commands/item/set.js.map +1 -0
- package/dist/commands/item/subitems.d.ts +50 -0
- package/dist/commands/item/subitems.d.ts.map +1 -0
- package/dist/commands/item/subitems.js +86 -0
- package/dist/commands/item/subitems.js.map +1 -0
- package/dist/commands/item/update.d.ts +99 -0
- package/dist/commands/item/update.d.ts.map +1 -0
- package/dist/commands/item/update.js +884 -0
- package/dist/commands/item/update.js.map +1 -0
- package/dist/commands/item/upsert.d.ts +105 -0
- package/dist/commands/item/upsert.d.ts.map +1 -0
- package/dist/commands/item/upsert.js +998 -0
- package/dist/commands/item/upsert.js.map +1 -0
- package/dist/commands/parse-argv.d.ts +20 -0
- package/dist/commands/parse-argv.d.ts.map +1 -0
- package/dist/commands/parse-argv.js +40 -0
- package/dist/commands/parse-argv.js.map +1 -0
- package/dist/commands/raw/index.d.ts +23 -0
- package/dist/commands/raw/index.d.ts.map +1 -0
- package/dist/commands/raw/index.js +416 -0
- package/dist/commands/raw/index.js.map +1 -0
- package/dist/commands/run-by-id-lookup.d.ts +72 -0
- package/dist/commands/run-by-id-lookup.d.ts.map +1 -0
- package/dist/commands/run-by-id-lookup.js +58 -0
- package/dist/commands/run-by-id-lookup.js.map +1 -0
- package/dist/commands/schema/index.d.ts +104 -0
- package/dist/commands/schema/index.d.ts.map +1 -0
- package/dist/commands/schema/index.js +183 -0
- package/dist/commands/schema/index.js.map +1 -0
- package/dist/commands/types.d.ts +66 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +15 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update/body-source.d.ts +38 -0
- package/dist/commands/update/body-source.d.ts.map +1 -0
- package/dist/commands/update/body-source.js +80 -0
- package/dist/commands/update/body-source.js.map +1 -0
- package/dist/commands/update/clear-all.d.ts +67 -0
- package/dist/commands/update/clear-all.d.ts.map +1 -0
- package/dist/commands/update/clear-all.js +281 -0
- package/dist/commands/update/clear-all.js.map +1 -0
- package/dist/commands/update/create.d.ts +51 -0
- package/dist/commands/update/create.d.ts.map +1 -0
- package/dist/commands/update/create.js +167 -0
- package/dist/commands/update/create.js.map +1 -0
- package/dist/commands/update/delete.d.ts +53 -0
- package/dist/commands/update/delete.d.ts.map +1 -0
- package/dist/commands/update/delete.js +148 -0
- package/dist/commands/update/delete.js.map +1 -0
- package/dist/commands/update/edit.d.ts +37 -0
- package/dist/commands/update/edit.d.ts.map +1 -0
- package/dist/commands/update/edit.js +129 -0
- package/dist/commands/update/edit.js.map +1 -0
- package/dist/commands/update/get.d.ts +37 -0
- package/dist/commands/update/get.d.ts.map +1 -0
- package/dist/commands/update/get.js +92 -0
- package/dist/commands/update/get.js.map +1 -0
- package/dist/commands/update/like.d.ts +17 -0
- package/dist/commands/update/like.d.ts.map +1 -0
- package/dist/commands/update/like.js +23 -0
- package/dist/commands/update/like.js.map +1 -0
- package/dist/commands/update/list.d.ts +58 -0
- package/dist/commands/update/list.d.ts.map +1 -0
- package/dist/commands/update/list.js +322 -0
- package/dist/commands/update/list.js.map +1 -0
- package/dist/commands/update/pin.d.ts +17 -0
- package/dist/commands/update/pin.d.ts.map +1 -0
- package/dist/commands/update/pin.js +23 -0
- package/dist/commands/update/pin.js.map +1 -0
- package/dist/commands/update/reply.d.ts +47 -0
- package/dist/commands/update/reply.d.ts.map +1 -0
- package/dist/commands/update/reply.js +149 -0
- package/dist/commands/update/reply.js.map +1 -0
- package/dist/commands/update/toggle.d.ts +70 -0
- package/dist/commands/update/toggle.d.ts.map +1 -0
- package/dist/commands/update/toggle.js +118 -0
- package/dist/commands/update/toggle.js.map +1 -0
- package/dist/commands/update/unlike.d.ts +17 -0
- package/dist/commands/update/unlike.d.ts.map +1 -0
- package/dist/commands/update/unlike.js +22 -0
- package/dist/commands/update/unlike.js.map +1 -0
- package/dist/commands/update/unpin.d.ts +17 -0
- package/dist/commands/update/unpin.d.ts.map +1 -0
- package/dist/commands/update/unpin.js +21 -0
- package/dist/commands/update/unpin.js.map +1 -0
- package/dist/commands/user/get.d.ts +31 -0
- package/dist/commands/user/get.d.ts.map +1 -0
- package/dist/commands/user/get.js +81 -0
- package/dist/commands/user/get.js.map +1 -0
- package/dist/commands/user/list.d.ts +61 -0
- package/dist/commands/user/list.d.ts.map +1 -0
- package/dist/commands/user/list.js +148 -0
- package/dist/commands/user/list.js.map +1 -0
- package/dist/commands/user/me.d.ts +17 -0
- package/dist/commands/user/me.d.ts.map +1 -0
- package/dist/commands/user/me.js +49 -0
- package/dist/commands/user/me.js.map +1 -0
- package/dist/commands/workspace/add-users.d.ts +76 -0
- package/dist/commands/workspace/add-users.d.ts.map +1 -0
- package/dist/commands/workspace/add-users.js +154 -0
- package/dist/commands/workspace/add-users.js.map +1 -0
- package/dist/commands/workspace/create.d.ts +59 -0
- package/dist/commands/workspace/create.d.ts.map +1 -0
- package/dist/commands/workspace/create.js +163 -0
- package/dist/commands/workspace/create.js.map +1 -0
- package/dist/commands/workspace/delete.d.ts +67 -0
- package/dist/commands/workspace/delete.d.ts.map +1 -0
- package/dist/commands/workspace/delete.js +182 -0
- package/dist/commands/workspace/delete.js.map +1 -0
- package/dist/commands/workspace/folders.d.ts +40 -0
- package/dist/commands/workspace/folders.d.ts.map +1 -0
- package/dist/commands/workspace/folders.js +124 -0
- package/dist/commands/workspace/folders.js.map +1 -0
- package/dist/commands/workspace/get.d.ts +35 -0
- package/dist/commands/workspace/get.d.ts.map +1 -0
- package/dist/commands/workspace/get.js +62 -0
- package/dist/commands/workspace/get.js.map +1 -0
- package/dist/commands/workspace/list.d.ts +57 -0
- package/dist/commands/workspace/list.d.ts.map +1 -0
- package/dist/commands/workspace/list.js +125 -0
- package/dist/commands/workspace/list.js.map +1 -0
- package/dist/commands/workspace/remove-users.d.ts +47 -0
- package/dist/commands/workspace/remove-users.d.ts.map +1 -0
- package/dist/commands/workspace/remove-users.js +122 -0
- package/dist/commands/workspace/remove-users.js.map +1 -0
- package/dist/commands/workspace/update.d.ts +68 -0
- package/dist/commands/workspace/update.d.ts.map +1 -0
- package/dist/commands/workspace/update.js +237 -0
- package/dist/commands/workspace/update.js.map +1 -0
- package/dist/config/load.d.ts +33 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +81 -0
- package/dist/config/load.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types/global-flags.d.ts +69 -0
- package/dist/types/global-flags.d.ts.map +1 -0
- package/dist/types/global-flags.js +170 -0
- package/dist/types/global-flags.js.map +1 -0
- package/dist/types/ids.d.ts +38 -0
- package/dist/types/ids.d.ts.map +1 -0
- package/dist/types/ids.js +51 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/json.d.ts +60 -0
- package/dist/types/json.d.ts.map +1 -0
- package/dist/types/json.js +33 -0
- package/dist/types/json.js.map +1 -0
- package/dist/utils/errors.d.ts +121 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +264 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +39 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +49 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/output/envelope.d.ts +140 -0
- package/dist/utils/output/envelope.d.ts.map +1 -0
- package/dist/utils/output/envelope.js +120 -0
- package/dist/utils/output/envelope.js.map +1 -0
- package/dist/utils/output/json.d.ts +10 -0
- package/dist/utils/output/json.d.ts.map +1 -0
- package/dist/utils/output/json.js +12 -0
- package/dist/utils/output/json.js.map +1 -0
- package/dist/utils/output/ndjson.d.ts +92 -0
- package/dist/utils/output/ndjson.d.ts.map +1 -0
- package/dist/utils/output/ndjson.js +33 -0
- package/dist/utils/output/ndjson.js.map +1 -0
- package/dist/utils/output/select.d.ts +22 -0
- package/dist/utils/output/select.d.ts.map +1 -0
- package/dist/utils/output/select.js +47 -0
- package/dist/utils/output/select.js.map +1 -0
- package/dist/utils/output/table.d.ts +32 -0
- package/dist/utils/output/table.d.ts.map +1 -0
- package/dist/utils/output/table.js +133 -0
- package/dist/utils/output/table.js.map +1 -0
- package/dist/utils/output/text.d.ts +5 -0
- package/dist/utils/output/text.d.ts.map +1 -0
- package/dist/utils/output/text.js +32 -0
- package/dist/utils/output/text.js.map +1 -0
- package/dist/utils/parse-boundary.d.ts +53 -0
- package/dist/utils/parse-boundary.d.ts.map +1 -0
- package/dist/utils/parse-boundary.js +62 -0
- package/dist/utils/parse-boundary.js.map +1 -0
- package/dist/utils/redact.d.ts +54 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +154 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/request-id.d.ts +17 -0
- package/dist/utils/request-id.d.ts.map +1 -0
- package/dist/utils/request-id.js +26 -0
- package/dist/utils/request-id.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `monday item upsert --board <bid> --name <n> --match-by <col>[,<col>...]
|
|
3
|
+
* [--set <col>=<val>]... [--set-raw <col>=<json>]... [--dry-run]`
|
|
4
|
+
* (`cli-design.md` §4.3 line 529, §5.8 + §6.4 + §6.5,
|
|
5
|
+
* `v0.2-plan.md` §3 M12).
|
|
6
|
+
*
|
|
7
|
+
* The idempotency-cluster verb. **0 matches** → branches to
|
|
8
|
+
* `create_item` (M9 wire surface). **1 match** → branches to the v0.1
|
|
9
|
+
* `item update` shape (synthetic `name` key bundled into
|
|
10
|
+
* `change_multiple_column_values` per §5.3 step 5; or
|
|
11
|
+
* `change_simple_column_value(column_id: "name")` when `--name` is the
|
|
12
|
+
* only diff). **2+ matches** → fails with `ambiguous_match` carrying
|
|
13
|
+
* `details.candidates: [{id, name}, ...]` capped at 10. The mutation
|
|
14
|
+
* envelope's `data.operation: "create_item" | "update_item"` exposes
|
|
15
|
+
* the branch on the success envelope; the dry-run encodes the same
|
|
16
|
+
* via `planned_changes[0].operation`.
|
|
17
|
+
*
|
|
18
|
+
* **Sequential-retry idempotent only** (cli-design §5.8 + §9.1). Two
|
|
19
|
+
* agents observing zero matches at the same instant both branch to
|
|
20
|
+
* `create_item`; the next call from either agent surfaces the
|
|
21
|
+
* duplicate as `ambiguous_match`. Concurrent-write protection via
|
|
22
|
+
* Monday's resource-locking mutations is a v0.4 candidate (cli-design
|
|
23
|
+
* §9.3). Race-mitigation guidance — pick a stable hidden-key column
|
|
24
|
+
* for `--match-by` and tighten the predicate so a duplicate from a
|
|
25
|
+
* race surfaces as `ambiguous_match` on the next call — lives in
|
|
26
|
+
* `--help` and §6.5.
|
|
27
|
+
*
|
|
28
|
+
* **Match-by semantics.** `--match-by <col>[,<col>...]` accepts
|
|
29
|
+
* comma-separated column tokens (resolved via the same column
|
|
30
|
+
* resolver `--set` uses) plus the literal `name` pseudo-token, which
|
|
31
|
+
* matches against the item's `name` field via Monday's `column_id:
|
|
32
|
+
* "name"` filter. Multiple tokens AND-combine — adding a token
|
|
33
|
+
* narrows the match set, so an agent seeing `ambiguous_match` knows
|
|
34
|
+
* widening the predicate by one column is the recovery path. Each
|
|
35
|
+
* column token's match value comes from the corresponding
|
|
36
|
+
* `--set <token>=<value>` (which is **required** for every match-by
|
|
37
|
+
* column token); the `name` token's match value comes from
|
|
38
|
+
* `--name <n>`. `--set-raw <col>=<json>` participates in column
|
|
39
|
+
* updates but **cannot appear in `--match-by`** because the JSON wire
|
|
40
|
+
* shape isn't a filter-comparable scalar — `usage_error` if an agent
|
|
41
|
+
* tries.
|
|
42
|
+
*
|
|
43
|
+
* **Mutation surface reuse, not entry-point reuse.** This module
|
|
44
|
+
* issues the same wire mutations `commands/item/create.ts` and
|
|
45
|
+
* `commands/item/update.ts` issue (CREATE_ITEM_MUTATION,
|
|
46
|
+
* CHANGE_SIMPLE_COLUMN_VALUE_MUTATION, CHANGE_COLUMN_VALUE_MUTATION,
|
|
47
|
+
* CHANGE_MULTIPLE_COLUMN_VALUES_MUTATION); the GraphQL strings are
|
|
48
|
+
* inlined here rather than imported because every existing site
|
|
49
|
+
* declares them locally too (the third-consumer trigger fires at the
|
|
50
|
+
* fourth+ site, not the third — see v0.2-plan §16's lift-on-third-
|
|
51
|
+
* consumer rule). The translator pipeline (`resolveAndTranslate` +
|
|
52
|
+
* `selectMutation` + `bundleColumnValues`) is the shared layer the
|
|
53
|
+
* three commands collapse onto, so the synthetic-`name` bundling +
|
|
54
|
+
* column-archived remap + `name + multi-column` atomicity contracts
|
|
55
|
+
* stay byte-identical across all three verbs.
|
|
56
|
+
*
|
|
57
|
+
* Idempotent: yes (sequential retry — re-running the same args
|
|
58
|
+
* yields the same item, with the second call hitting the update
|
|
59
|
+
* branch).
|
|
60
|
+
*/
|
|
61
|
+
import { z } from 'zod';
|
|
62
|
+
import { ensureSubcommand } from '../types.js';
|
|
63
|
+
import { emitDryRun, emitMutation } from '../emit.js';
|
|
64
|
+
import { resolveClient } from '../../api/resolve-client.js';
|
|
65
|
+
import { BoardIdSchema } from '../../types/ids.js';
|
|
66
|
+
import { parseArgv } from '../parse-argv.js';
|
|
67
|
+
import { ApiError, MondayCliError, UsageError } from '../../utils/errors.js';
|
|
68
|
+
import { bundleColumnValues, selectMutation, } from '../../api/column-values.js';
|
|
69
|
+
import { parseSetRawExpression, } from '../../api/raw-write.js';
|
|
70
|
+
import { splitSetExpression, } from '../../api/set-expression.js';
|
|
71
|
+
import { buildResolutionContexts } from '../../api/resolution-context.js';
|
|
72
|
+
import { SourceAggregator, mergeSource, mergeCacheAge, mergeSourceWithPreflight, } from '../../api/source-aggregator.js';
|
|
73
|
+
import { resolveAndTranslate } from '../../api/resolution-pass.js';
|
|
74
|
+
import { foldAndRemap } from '../../api/resolver-error-fold.js';
|
|
75
|
+
import { planChanges, planCreate } from '../../api/dry-run.js';
|
|
76
|
+
import { loadBoardMetadata, refreshBoardMetadata, } from '../../api/board-metadata.js';
|
|
77
|
+
import { buildQueryParams } from '../../api/filters.js';
|
|
78
|
+
import { fetchItemsPage } from '../../api/items-page-walker.js';
|
|
79
|
+
import { ITEM_FIELDS_FRAGMENT, resolveMeFactory, } from '../../api/item-helpers.js';
|
|
80
|
+
import { projectMutationItem } from '../../api/item-mutation-result.js';
|
|
81
|
+
import { projectedItemSchema, } from '../../api/item-projection.js';
|
|
82
|
+
// ============================================================
|
|
83
|
+
// GraphQL — mutation surface (lookup uses the shared
|
|
84
|
+
// `fetchItemsPage` helper from `api/items-page-walker.ts` lifted
|
|
85
|
+
// post-M12 per §18 R34; the helper builds the `boards.items_page`
|
|
86
|
+
// query inline from `operationName` + `itemFields` + `queryParams`,
|
|
87
|
+
// so the lookup mirrors `item update --where`'s wire shape without
|
|
88
|
+
// a per-file GraphQL constant).
|
|
89
|
+
// ============================================================
|
|
90
|
+
/**
|
|
91
|
+
* Match-by lookup uses `fetchItemsPage` directly with `limit: 11` —
|
|
92
|
+
* the 11th item exists only when ≥11 candidates match, which already
|
|
93
|
+
* gives `ambiguous_match` plus 10 capped candidates the §6.5 details
|
|
94
|
+
* schema documents. No `next_items_page` continuation: the planner
|
|
95
|
+
* caps at 10 candidates, so a non-null cursor on the first page
|
|
96
|
+
* is the 2+ signal.
|
|
97
|
+
*/
|
|
98
|
+
const UPSERT_LOOKUP_ITEM_FIELDS = `id
|
|
99
|
+
name`;
|
|
100
|
+
const CREATE_ITEM_MUTATION = `
|
|
101
|
+
mutation ItemUpsertCreate(
|
|
102
|
+
$boardId: ID!
|
|
103
|
+
$itemName: String!
|
|
104
|
+
$columnValues: JSON
|
|
105
|
+
$createLabelsIfMissing: Boolean
|
|
106
|
+
) {
|
|
107
|
+
create_item(
|
|
108
|
+
board_id: $boardId
|
|
109
|
+
item_name: $itemName
|
|
110
|
+
column_values: $columnValues
|
|
111
|
+
create_labels_if_missing: $createLabelsIfMissing
|
|
112
|
+
) {
|
|
113
|
+
${ITEM_FIELDS_FRAGMENT}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
const CHANGE_SIMPLE_COLUMN_VALUE_MUTATION = `
|
|
118
|
+
mutation ItemUpsertSimple(
|
|
119
|
+
$itemId: ID!
|
|
120
|
+
$boardId: ID!
|
|
121
|
+
$columnId: String!
|
|
122
|
+
$value: String!
|
|
123
|
+
$createLabelsIfMissing: Boolean
|
|
124
|
+
) {
|
|
125
|
+
change_simple_column_value(
|
|
126
|
+
item_id: $itemId
|
|
127
|
+
board_id: $boardId
|
|
128
|
+
column_id: $columnId
|
|
129
|
+
value: $value
|
|
130
|
+
create_labels_if_missing: $createLabelsIfMissing
|
|
131
|
+
) {
|
|
132
|
+
${ITEM_FIELDS_FRAGMENT}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
`;
|
|
136
|
+
const CHANGE_COLUMN_VALUE_MUTATION = `
|
|
137
|
+
mutation ItemUpsertRich(
|
|
138
|
+
$itemId: ID!
|
|
139
|
+
$boardId: ID!
|
|
140
|
+
$columnId: String!
|
|
141
|
+
$value: JSON!
|
|
142
|
+
$createLabelsIfMissing: Boolean
|
|
143
|
+
) {
|
|
144
|
+
change_column_value(
|
|
145
|
+
item_id: $itemId
|
|
146
|
+
board_id: $boardId
|
|
147
|
+
column_id: $columnId
|
|
148
|
+
value: $value
|
|
149
|
+
create_labels_if_missing: $createLabelsIfMissing
|
|
150
|
+
) {
|
|
151
|
+
${ITEM_FIELDS_FRAGMENT}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
const CHANGE_MULTIPLE_COLUMN_VALUES_MUTATION = `
|
|
156
|
+
mutation ItemUpsertMulti(
|
|
157
|
+
$itemId: ID!
|
|
158
|
+
$boardId: ID!
|
|
159
|
+
$columnValues: JSON!
|
|
160
|
+
$createLabelsIfMissing: Boolean
|
|
161
|
+
) {
|
|
162
|
+
change_multiple_column_values(
|
|
163
|
+
item_id: $itemId
|
|
164
|
+
board_id: $boardId
|
|
165
|
+
column_values: $columnValues
|
|
166
|
+
create_labels_if_missing: $createLabelsIfMissing
|
|
167
|
+
) {
|
|
168
|
+
${ITEM_FIELDS_FRAGMENT}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
`;
|
|
172
|
+
// ============================================================
|
|
173
|
+
// Wire response zod schemas (parse-boundary discipline, R18).
|
|
174
|
+
// ============================================================
|
|
175
|
+
const lookupItemSchema = z
|
|
176
|
+
.object({
|
|
177
|
+
id: z.string().min(1),
|
|
178
|
+
name: z.string(),
|
|
179
|
+
})
|
|
180
|
+
.loose();
|
|
181
|
+
// ============================================================
|
|
182
|
+
// Output schema — projected item + operation discriminator.
|
|
183
|
+
// ============================================================
|
|
184
|
+
const operationEnum = z.enum(['create_item', 'update_item']);
|
|
185
|
+
export const itemUpsertOutputSchema = projectedItemSchema.extend({
|
|
186
|
+
/**
|
|
187
|
+
* Branch discriminator per cli-design §6.4 + v0.2-plan §3 M12.
|
|
188
|
+
* `"create_item"` when the lookup found 0 matches; `"update_item"`
|
|
189
|
+
* when it found exactly 1. The slot lives on `data` (rather than
|
|
190
|
+
* `meta`) because v0.1's mutation envelope already keeps
|
|
191
|
+
* operation-shape signals in `data` — `meta` is reserved for
|
|
192
|
+
* cross-verb cache / source / pagination state. Codex round-2 P2.
|
|
193
|
+
*/
|
|
194
|
+
operation: operationEnum,
|
|
195
|
+
});
|
|
196
|
+
// ============================================================
|
|
197
|
+
// Input schema + dispatch.
|
|
198
|
+
// ============================================================
|
|
199
|
+
/**
|
|
200
|
+
* The literal pseudo-token `--match-by` accepts to match against the
|
|
201
|
+
* item's `name` field. Case-sensitive — agents need a deterministic
|
|
202
|
+
* token; lowercase `name` is the convention `cli-design.md` §5.8
|
|
203
|
+
* pins. Column tokens that happen to be titled `Name` (capitalised)
|
|
204
|
+
* still resolve through the column resolver per the normal title-
|
|
205
|
+
* resolution rules; this constant is the *pseudo*-column escape.
|
|
206
|
+
*/
|
|
207
|
+
const NAME_PSEUDO_TOKEN = 'name';
|
|
208
|
+
const inputSchema = z
|
|
209
|
+
.object({
|
|
210
|
+
board: BoardIdSchema,
|
|
211
|
+
name: z.string().refine((s) => s.trim().length > 0, {
|
|
212
|
+
message: '--name must be non-empty (whitespace-only is rejected)',
|
|
213
|
+
}),
|
|
214
|
+
matchBy: z
|
|
215
|
+
.array(z.string())
|
|
216
|
+
.min(1, '--match-by requires at least one token'),
|
|
217
|
+
set: z.array(z.string()).default([]),
|
|
218
|
+
setRaw: z.array(z.string()).default([]),
|
|
219
|
+
createLabelsIfMissing: z.boolean().optional(),
|
|
220
|
+
})
|
|
221
|
+
.strict();
|
|
222
|
+
/**
|
|
223
|
+
* Splits the comma-separated `--match-by` argv into individual tokens
|
|
224
|
+
* + de-duplicates. Trims whitespace; rejects empty tokens
|
|
225
|
+
* (`--match-by status,,owner` is a usage error, not a silent drop).
|
|
226
|
+
*/
|
|
227
|
+
const parseMatchByTokens = (raw) => {
|
|
228
|
+
const tokens = [];
|
|
229
|
+
const seen = new Set();
|
|
230
|
+
for (const r of raw) {
|
|
231
|
+
for (const piece of r.split(',')) {
|
|
232
|
+
const trimmed = piece.trim();
|
|
233
|
+
if (trimmed.length === 0) {
|
|
234
|
+
throw new UsageError('--match-by entries must not be empty (an empty segment between ' +
|
|
235
|
+
'commas, or a whitespace-only token, was rejected).', { details: { raw } });
|
|
236
|
+
}
|
|
237
|
+
if (seen.has(trimmed)) {
|
|
238
|
+
throw new UsageError(`--match-by tokens must be unique; ${JSON.stringify(trimmed)} ` +
|
|
239
|
+
`appeared more than once.`, { details: { token: trimmed } });
|
|
240
|
+
}
|
|
241
|
+
seen.add(trimmed);
|
|
242
|
+
tokens.push(trimmed);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return tokens;
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Pairs each match-by token with its match value. For the `name`
|
|
249
|
+
* pseudo-token the value is `--name <n>`; for every column token,
|
|
250
|
+
* the value is the corresponding `--set <token>=<value>`. Throws
|
|
251
|
+
* `usage_error` with token-specific guidance when the pairing fails.
|
|
252
|
+
*
|
|
253
|
+
* `--set-raw` entries cannot supply match values — the JSON wire
|
|
254
|
+
* shape isn't a filter-comparable scalar. The check is at parse-
|
|
255
|
+
* boundary (resolution-free), so a malformed match-by pairing fails
|
|
256
|
+
* before any network call.
|
|
257
|
+
*/
|
|
258
|
+
const buildMatchByEntries = (inputs) => {
|
|
259
|
+
const entries = [];
|
|
260
|
+
// Index --set entries by token for O(1) lookup. `splitSetExpression`
|
|
261
|
+
// preserves the agent's verbatim token (no normalisation), so the
|
|
262
|
+
// match-by token must be character-equal to the --set token.
|
|
263
|
+
const setByToken = new Map();
|
|
264
|
+
for (const e of inputs.setEntries) {
|
|
265
|
+
setByToken.set(e.token, e);
|
|
266
|
+
}
|
|
267
|
+
for (const token of inputs.tokens) {
|
|
268
|
+
if (token === NAME_PSEUDO_TOKEN) {
|
|
269
|
+
entries.push({ kind: 'name', token: 'name', value: inputs.name });
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (inputs.rawTokens.has(token)) {
|
|
273
|
+
throw new UsageError(`--match-by ${JSON.stringify(token)} cannot be paired with a ` +
|
|
274
|
+
`--set-raw entry; the JSON wire shape isn't a filter-comparable ` +
|
|
275
|
+
`scalar. Pass the same column via --set <token>=<scalar> for ` +
|
|
276
|
+
`match-by, or drop ${JSON.stringify(token)} from --match-by.`, { details: { token } });
|
|
277
|
+
}
|
|
278
|
+
const setEntry = setByToken.get(token);
|
|
279
|
+
if (setEntry === undefined) {
|
|
280
|
+
throw new UsageError(`--match-by ${JSON.stringify(token)} requires a corresponding ` +
|
|
281
|
+
`--set ${token}=<value> (the upsert pulls the match value from ` +
|
|
282
|
+
`--set so the create branch and the lookup share one source of ` +
|
|
283
|
+
`truth). Add --set ${token}=<value>, or drop ` +
|
|
284
|
+
`${JSON.stringify(token)} from --match-by.`, { details: { token } });
|
|
285
|
+
}
|
|
286
|
+
entries.push({ kind: 'column', token, value: setEntry.value });
|
|
287
|
+
}
|
|
288
|
+
return entries;
|
|
289
|
+
};
|
|
290
|
+
/**
|
|
291
|
+
* Resolves the column-token half of `--match-by` against the board's
|
|
292
|
+
* metadata, builds the `query_params.rules` payload, and queries
|
|
293
|
+
* `items_page` once with `limit: 11` so the 0 / 1 / 2+ branch
|
|
294
|
+
* decision needs no second round-trip.
|
|
295
|
+
*
|
|
296
|
+
* Column-token rules go through `buildQueryParams` — the same path
|
|
297
|
+
* `item list --where` and bulk `item update --where` use (note: `item
|
|
298
|
+
* search` parses identical syntax via `buildColumnQueries` but hits
|
|
299
|
+
* Monday's `items_page_by_column_values` endpoint, a different filter
|
|
300
|
+
* shape) — so per-column-type
|
|
301
|
+
* value resolution (the `me` token for people columns, the same
|
|
302
|
+
* cache-miss-refresh + collision-warning collection) inherits
|
|
303
|
+
* automatically. `name` pseudo-tokens skip the column resolver
|
|
304
|
+
* entirely (Monday accepts `column_id: "name"` in `query_params.rules`
|
|
305
|
+
* as a built-in filter against the item's `name` field, no metadata
|
|
306
|
+
* lookup needed) and are prepended to the rules array post-build.
|
|
307
|
+
*
|
|
308
|
+
* **Known v0.2 round-trip limits (cli-design §5.8 caveat).** The
|
|
309
|
+
* lookup leg and the `--set` translator have asymmetric grammars,
|
|
310
|
+
* so only a subset of column kinds round-trip cleanly when the same
|
|
311
|
+
* column appears in both `--match-by` and `--set`:
|
|
312
|
+
*
|
|
313
|
+
* - **People:** only `me` (resolved on both legs). Emails resolve
|
|
314
|
+
* in `--set` but pass verbatim in lookup; raw numeric user IDs
|
|
315
|
+
* are rejected by the people `--set` grammar (cli-design §5.3
|
|
316
|
+
* step 3, M5b deferral).
|
|
317
|
+
* - **Date:** NOT v0.2-safe — Monday's items_page filter requires
|
|
318
|
+
* `compare_value: ["EXACT", "YYYY-MM-DD"]` for date-equals,
|
|
319
|
+
* but `buildQueryParams` emits a bare-ISO `["YYYY-MM-DD"]` (the
|
|
320
|
+
* same shape `item search` / `item update --where` ship). The
|
|
321
|
+
* EXACT-marker lift is a cross-surface v0.3 candidate.
|
|
322
|
+
* - **Status / dropdown:** label text (e.g. `Backlog`) round-trips
|
|
323
|
+
* because Monday's filter compares against the stored label.
|
|
324
|
+
* - **Text / long_text / numbers / item name / external_id-shaped
|
|
325
|
+
* hidden text:** verbatim pass-through on both legs.
|
|
326
|
+
* - **Link / email / phone (rich pipe grammar):** the friendly
|
|
327
|
+
* `<scalar>|<text>` write parses to `{url, text}` / `{email,
|
|
328
|
+
* text}` / `{phone, country}` but the lookup leg sends the
|
|
329
|
+
* literal pipe string — best-effort only.
|
|
330
|
+
*
|
|
331
|
+
* The recommended canonical pattern is a stable hidden text /
|
|
332
|
+
* external_id column as the synthetic key. Email→ID, numeric-user-
|
|
333
|
+
* ID acceptance, relative-date resolution, and the date EXACT-
|
|
334
|
+
* marker lift are v0.3 cross-surface follow-ups (would lift `item
|
|
335
|
+
* search` and `item update --where` simultaneously).
|
|
336
|
+
*/
|
|
337
|
+
const lookupMatches = async (inputs) => {
|
|
338
|
+
// Split into name + column tokens. Column tokens go through the
|
|
339
|
+
// shared filter pipeline; name tokens contribute a literal
|
|
340
|
+
// `column_id: "name"` rule prepended to the resulting rules array.
|
|
341
|
+
const columnEntries = inputs.matchBy.filter((e) => e.kind === 'column');
|
|
342
|
+
const nameEntries = inputs.matchBy.filter((e) => e.kind === 'name');
|
|
343
|
+
// Convert column match-by entries to `--where`-shaped strings and
|
|
344
|
+
// hand to the shared filter pipeline. `splitSetExpression` and
|
|
345
|
+
// `parseWhereSyntax` both split on first `=`, so a value containing
|
|
346
|
+
// `=` round-trips correctly.
|
|
347
|
+
const whereClauses = columnEntries.map((e) => `${e.token}=${e.value}`);
|
|
348
|
+
const filterResult = await buildQueryParams({
|
|
349
|
+
metadata: inputs.metadata,
|
|
350
|
+
resolveMe: resolveMeFactory(inputs.client),
|
|
351
|
+
whereClauses,
|
|
352
|
+
filterJson: undefined,
|
|
353
|
+
...(inputs.onColumnNotFound === undefined
|
|
354
|
+
? {}
|
|
355
|
+
: { onColumnNotFound: inputs.onColumnNotFound }),
|
|
356
|
+
});
|
|
357
|
+
// Prepend the `name` pseudo-token rules. Monday accepts
|
|
358
|
+
// `column_id: "name"` in `query_params.rules` as a built-in filter
|
|
359
|
+
// against the item's `name` field — no column resolution needed.
|
|
360
|
+
const nameRules = nameEntries.map((e) => ({
|
|
361
|
+
column_id: 'name',
|
|
362
|
+
operator: 'any_of',
|
|
363
|
+
compare_value: [e.value],
|
|
364
|
+
}));
|
|
365
|
+
const columnRules = filterResult.queryParams?.rules ?? [];
|
|
366
|
+
const rules = [...nameRules, ...columnRules];
|
|
367
|
+
const lookup = await fetchItemsPage({
|
|
368
|
+
client: inputs.client,
|
|
369
|
+
operationName: 'ItemUpsertLookup',
|
|
370
|
+
boardId: inputs.boardId,
|
|
371
|
+
limit: 11,
|
|
372
|
+
queryParams: { rules },
|
|
373
|
+
itemFields: UPSERT_LOOKUP_ITEM_FIELDS,
|
|
374
|
+
itemSchema: lookupItemSchema,
|
|
375
|
+
});
|
|
376
|
+
return {
|
|
377
|
+
items: lookup.data.items,
|
|
378
|
+
hasMore: lookup.data.cursor !== null,
|
|
379
|
+
// Filter pipeline returns `Warning` shape; resolver-warning
|
|
380
|
+
// codes (`column_token_collision`, `stale_cache_refreshed`)
|
|
381
|
+
// structurally widen to ResolverWarning cleanly.
|
|
382
|
+
warnings: filterResult.warnings,
|
|
383
|
+
refreshed: filterResult.refreshed,
|
|
384
|
+
metadata: inputs.metadata,
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
const decideBranch = (inputs) => {
|
|
388
|
+
const items = inputs.lookup.items;
|
|
389
|
+
// 0 matches → create branch only when the page is definitively
|
|
390
|
+
// empty (cursor null). An empty page with a non-null cursor is a
|
|
391
|
+
// Monday API anomaly (the items_page contract returns `cursor:
|
|
392
|
+
// null` when no more pages exist) — we can't prove there are zero
|
|
393
|
+
// matches, so fail-closed with internal_error rather than create
|
|
394
|
+
// a duplicate. Codex round-1 F3.
|
|
395
|
+
if (items.length === 0) {
|
|
396
|
+
if (inputs.lookup.hasMore) {
|
|
397
|
+
throw new ApiError('internal_error', `item upsert lookup returned an empty page with a non-null cursor on board ${inputs.boardId}; ` +
|
|
398
|
+
`Monday's items_page contract returns cursor: null when no more matches exist. ` +
|
|
399
|
+
`Refusing to create-or-update without a definitive 0/1/2+ count. ` +
|
|
400
|
+
`Re-run; if the issue persists, file a bug.`, {
|
|
401
|
+
details: {
|
|
402
|
+
board_id: inputs.boardId,
|
|
403
|
+
match_by: inputs.matchBy.map((e) => e.token),
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return { kind: 'create' };
|
|
408
|
+
}
|
|
409
|
+
if (items.length === 1 && !inputs.lookup.hasMore) {
|
|
410
|
+
// c8 ignore — defensive: items.length === 1 narrowing guarantees
|
|
411
|
+
// items[0] is non-undefined.
|
|
412
|
+
const only = items[0];
|
|
413
|
+
/* c8 ignore next 3 */
|
|
414
|
+
if (only === undefined) {
|
|
415
|
+
throw new ApiError('internal_error', 'decideBranch: empty single match');
|
|
416
|
+
}
|
|
417
|
+
return { kind: 'update', itemId: only.id };
|
|
418
|
+
}
|
|
419
|
+
// 2+ matches OR (1 match AND `cursor !== null` → at least 2 across
|
|
420
|
+
// pages). cli-design §6.5 caps the candidates display at 10.
|
|
421
|
+
const candidates = items
|
|
422
|
+
.slice(0, 10)
|
|
423
|
+
.map((i) => ({ id: i.id, name: i.name }));
|
|
424
|
+
const matchValues = {};
|
|
425
|
+
for (const e of inputs.matchBy) {
|
|
426
|
+
matchValues[e.token] = e.value;
|
|
427
|
+
}
|
|
428
|
+
const error = new ApiError('ambiguous_match', `item upsert matched ${String(items.length)} item(s) on board ${inputs.boardId} ` +
|
|
429
|
+
`with the supplied --match-by; pick a tighter predicate (add another ` +
|
|
430
|
+
`--match-by column, or use a stable hidden-key column) so the next ` +
|
|
431
|
+
`call resolves to a single item.`, {
|
|
432
|
+
details: {
|
|
433
|
+
board_id: inputs.boardId,
|
|
434
|
+
match_by: inputs.matchBy.map((e) => e.token),
|
|
435
|
+
match_values: matchValues,
|
|
436
|
+
matched_count: items.length,
|
|
437
|
+
candidates,
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
return { kind: 'ambiguous', error };
|
|
441
|
+
};
|
|
442
|
+
const executeCreate = async (inputs) => {
|
|
443
|
+
const response = await inputs.client.raw(CREATE_ITEM_MUTATION, {
|
|
444
|
+
boardId: inputs.boardId,
|
|
445
|
+
itemName: inputs.itemName,
|
|
446
|
+
columnValues: inputs.columnValues,
|
|
447
|
+
createLabelsIfMissing: inputs.createLabelsIfMissing ?? false,
|
|
448
|
+
}, { operationName: 'ItemUpsertCreate' });
|
|
449
|
+
return {
|
|
450
|
+
projected: projectMutationItem({
|
|
451
|
+
raw: response.data.create_item,
|
|
452
|
+
// create_item returns a fresh ID; we don't have one to project
|
|
453
|
+
// against, so the helper falls back to its own check. Pass empty
|
|
454
|
+
// string to indicate "no expected ID" — projectMutationItem
|
|
455
|
+
// surfaces internal_error if Monday returned a null payload.
|
|
456
|
+
itemId: '',
|
|
457
|
+
errorCode: 'internal_error',
|
|
458
|
+
errorMessage: 'Monday returned no item payload from create_item during upsert.',
|
|
459
|
+
}),
|
|
460
|
+
response,
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
const executeUpdate = async (inputs) => {
|
|
464
|
+
const labelsFlag = inputs.createLabelsIfMissing ?? false;
|
|
465
|
+
if (inputs.mutation.kind === 'change_simple_column_value') {
|
|
466
|
+
const response = await inputs.client.raw(CHANGE_SIMPLE_COLUMN_VALUE_MUTATION, {
|
|
467
|
+
itemId: inputs.itemId,
|
|
468
|
+
boardId: inputs.boardId,
|
|
469
|
+
columnId: inputs.mutation.columnId,
|
|
470
|
+
value: inputs.mutation.value,
|
|
471
|
+
createLabelsIfMissing: labelsFlag,
|
|
472
|
+
}, { operationName: 'ItemUpsertSimple' });
|
|
473
|
+
return {
|
|
474
|
+
projected: projectMutationItem({
|
|
475
|
+
raw: response.data.change_simple_column_value,
|
|
476
|
+
itemId: inputs.itemId,
|
|
477
|
+
errorCode: 'internal_error',
|
|
478
|
+
errorMessage: `Monday returned no item payload from the mutation for id ${inputs.itemId}.`,
|
|
479
|
+
}),
|
|
480
|
+
response,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/* c8 ignore start — defensive: in upsert's update branch the
|
|
484
|
+
synthetic `name` translated value always joins the array, so the
|
|
485
|
+
one-rich-only (single-entry rich) shape that selectMutation maps
|
|
486
|
+
to `change_column_value` is unreachable: 0 user --set entries +
|
|
487
|
+
name = 1 simple entry → `change_simple_column_value`; 1+ user
|
|
488
|
+
--set entries + name = 2+ entries → `change_multiple_column_
|
|
489
|
+
values`. The branch is kept exhaustive so a future shape change
|
|
490
|
+
(e.g. dropping the synthetic name on a no-rename code path) can
|
|
491
|
+
opt back in without re-deriving the mutation dispatch. */
|
|
492
|
+
if (inputs.mutation.kind === 'change_column_value') {
|
|
493
|
+
const response = await inputs.client.raw(CHANGE_COLUMN_VALUE_MUTATION, {
|
|
494
|
+
itemId: inputs.itemId,
|
|
495
|
+
boardId: inputs.boardId,
|
|
496
|
+
columnId: inputs.mutation.columnId,
|
|
497
|
+
value: inputs.mutation.value,
|
|
498
|
+
createLabelsIfMissing: labelsFlag,
|
|
499
|
+
}, { operationName: 'ItemUpsertRich' });
|
|
500
|
+
return {
|
|
501
|
+
projected: projectMutationItem({
|
|
502
|
+
raw: response.data.change_column_value,
|
|
503
|
+
itemId: inputs.itemId,
|
|
504
|
+
errorCode: 'internal_error',
|
|
505
|
+
errorMessage: `Monday returned no item payload from the mutation for id ${inputs.itemId}.`,
|
|
506
|
+
}),
|
|
507
|
+
response,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
/* c8 ignore stop */
|
|
511
|
+
// change_multiple_column_values — multi-`--set` or `--set + --name`.
|
|
512
|
+
const response = await inputs.client.raw(CHANGE_MULTIPLE_COLUMN_VALUES_MUTATION, {
|
|
513
|
+
itemId: inputs.itemId,
|
|
514
|
+
boardId: inputs.boardId,
|
|
515
|
+
columnValues: inputs.mutation.columnValues,
|
|
516
|
+
createLabelsIfMissing: labelsFlag,
|
|
517
|
+
}, { operationName: 'ItemUpsertMulti' });
|
|
518
|
+
return {
|
|
519
|
+
projected: projectMutationItem({
|
|
520
|
+
raw: response.data.change_multiple_column_values,
|
|
521
|
+
itemId: inputs.itemId,
|
|
522
|
+
errorCode: 'internal_error',
|
|
523
|
+
errorMessage: `Monday returned no item payload from the mutation for id ${inputs.itemId}.`,
|
|
524
|
+
}),
|
|
525
|
+
response,
|
|
526
|
+
};
|
|
527
|
+
};
|
|
528
|
+
// ============================================================
|
|
529
|
+
// Main command export.
|
|
530
|
+
// ============================================================
|
|
531
|
+
export const itemUpsertCommand = {
|
|
532
|
+
name: 'item.upsert',
|
|
533
|
+
summary: 'Create-or-update an item by --match-by predicate (idempotent)',
|
|
534
|
+
examples: [
|
|
535
|
+
'monday item upsert --board 67890 --name "Refactor login" --match-by name --set status=Backlog',
|
|
536
|
+
'monday item upsert --board 67890 --name "Refactor login" --match-by external_id --set external_id=ABC-123 --set status=Backlog',
|
|
537
|
+
'monday item upsert --board 67890 --name "Refactor login" --match-by name,owner --set owner=me --set status=Backlog',
|
|
538
|
+
'monday item upsert --board 67890 --name "Refactor login" --match-by name,priority --set priority=High --set status=Backlog',
|
|
539
|
+
'monday item upsert --board 67890 --name "Refactor login" --match-by name --set status=Backlog --dry-run --json',
|
|
540
|
+
],
|
|
541
|
+
// Sequential-retry idempotent — see file header + cli-design §5.8.
|
|
542
|
+
// The CommandModule flag is a coarse boolean; the nuanced contract
|
|
543
|
+
// lives in --help / docs / §9.1.
|
|
544
|
+
idempotent: true,
|
|
545
|
+
inputSchema,
|
|
546
|
+
outputSchema: itemUpsertOutputSchema,
|
|
547
|
+
attach: (program, ctx) => {
|
|
548
|
+
const noun = ensureSubcommand(program, 'item', 'Item commands');
|
|
549
|
+
noun
|
|
550
|
+
.command('upsert')
|
|
551
|
+
.description(itemUpsertCommand.summary)
|
|
552
|
+
.requiredOption('--board <bid>', 'board ID (required)')
|
|
553
|
+
.requiredOption('--name <n>', 'item name (required, non-empty)')
|
|
554
|
+
.requiredOption('--match-by <list>', 'comma-separated match tokens (column tokens + literal `name`)', (value, prev) => [...prev, value], [])
|
|
555
|
+
.option('--set <expr>', 'repeatable <col>=<val>. Required for every non-`name` --match-by token.', (value, prev) => [...prev, value], [])
|
|
556
|
+
.option('--set-raw <expr>', 'repeatable <col>=<json> raw write (column updates only — cannot appear in --match-by)', (value, prev) => [...prev, value], [])
|
|
557
|
+
.option('--create-labels-if-missing', 'auto-create unknown status / dropdown labels (Monday flag)')
|
|
558
|
+
.addHelpText('after', [
|
|
559
|
+
'',
|
|
560
|
+
'Examples:',
|
|
561
|
+
...itemUpsertCommand.examples.map((e) => ` ${e}`),
|
|
562
|
+
'',
|
|
563
|
+
'Race-mitigation note: upsert is sequential-retry idempotent only.',
|
|
564
|
+
'Two concurrent agents observing zero matches both branch to',
|
|
565
|
+
'create_item; the next call surfaces the duplicate as',
|
|
566
|
+
'ambiguous_match. Pick a stable hidden-key column for --match-by',
|
|
567
|
+
'so race-induced duplicates are recoverable.',
|
|
568
|
+
'',
|
|
569
|
+
'Match-value caveats (per column kind). The lookup leg and the',
|
|
570
|
+
'--set translator have asymmetric grammars in v0.2, so only a',
|
|
571
|
+
'subset of column kinds round-trip cleanly when used in both',
|
|
572
|
+
'--match-by and --set:',
|
|
573
|
+
'',
|
|
574
|
+
' Always safe (verbatim pass-through on both legs):',
|
|
575
|
+
' - name (the item-name pseudo-token)',
|
|
576
|
+
' - text / long_text',
|
|
577
|
+
' - numbers',
|
|
578
|
+
' - external_id-shaped hidden text',
|
|
579
|
+
' Safe via label-text:',
|
|
580
|
+
' - status / dropdown (pass the label name, not the index)',
|
|
581
|
+
' Restricted to one value:',
|
|
582
|
+
' - people: only `me` round-trips. Emails work in --set but',
|
|
583
|
+
' pass verbatim in lookup (duplicate); raw numeric user',
|
|
584
|
+
' IDs are rejected by the --set grammar (cli-design §5.3).',
|
|
585
|
+
' Not v0.2-safe:',
|
|
586
|
+
' - date: Monday items_page requires an EXACT marker plus',
|
|
587
|
+
' YYYY-MM-DD for date-equals comparisons; the lookup leg',
|
|
588
|
+
' sends bare ISO, so an upsert against a date column',
|
|
589
|
+
' duplicates on rerun.',
|
|
590
|
+
' - link / email / phone: the rich `scalar|text` write',
|
|
591
|
+
' grammar produces a `{url,text}` / `{email,text}` /',
|
|
592
|
+
' `{phone,country}` payload that the bare-string filter',
|
|
593
|
+
' compare cannot match against.',
|
|
594
|
+
'',
|
|
595
|
+
'Recommended canonical pattern: stable hidden text /',
|
|
596
|
+
'external_id column as the synthetic key. Email->ID,',
|
|
597
|
+
'numeric-user-ID acceptance, relative-date resolution, and',
|
|
598
|
+
'the date EXACT-marker lift are v0.3 cross-surface follow-ups',
|
|
599
|
+
'(would also lift `item search` and `item update --where`).',
|
|
600
|
+
'',
|
|
601
|
+
].join('\n'))
|
|
602
|
+
.action(async (opts) => {
|
|
603
|
+
const parsed = parseArgv(itemUpsertCommand.inputSchema, opts);
|
|
604
|
+
const { client, globalFlags, apiVersion, toEmit } = resolveClient(ctx, program.opts());
|
|
605
|
+
// Argv-parse-time failures fire BEFORE any network call.
|
|
606
|
+
// Splits + JSON parse run on pure strings; surfacing here
|
|
607
|
+
// means a malformed --set / --set-raw / --match-by fails fast
|
|
608
|
+
// without burning a board-metadata fetch + lookup round-trip.
|
|
609
|
+
// Same fail-fast invariant as item update / item create.
|
|
610
|
+
const setEntries = parsed.set.map(splitSetExpression);
|
|
611
|
+
const rawEntries = parsed.setRaw.map(parseSetRawExpression);
|
|
612
|
+
const matchByTokens = parseMatchByTokens(parsed.matchBy);
|
|
613
|
+
const rawTokens = new Set(rawEntries.map((r) => r.token));
|
|
614
|
+
const matchByEntries = buildMatchByEntries({
|
|
615
|
+
tokens: matchByTokens,
|
|
616
|
+
setEntries,
|
|
617
|
+
rawTokens,
|
|
618
|
+
name: parsed.name,
|
|
619
|
+
});
|
|
620
|
+
// Load board metadata once — every leg (lookup, dry-run /
|
|
621
|
+
// live mutation, column resolver) consumes the same view.
|
|
622
|
+
const meta = await loadBoardMetadata({
|
|
623
|
+
client,
|
|
624
|
+
boardId: parsed.board,
|
|
625
|
+
env: ctx.env,
|
|
626
|
+
noCache: globalFlags.noCache,
|
|
627
|
+
});
|
|
628
|
+
const onColumnNotFound = meta.source === 'cache'
|
|
629
|
+
? async () => {
|
|
630
|
+
const refreshed = await refreshBoardMetadata({
|
|
631
|
+
client,
|
|
632
|
+
boardId: parsed.board,
|
|
633
|
+
env: ctx.env,
|
|
634
|
+
});
|
|
635
|
+
return refreshed.metadata;
|
|
636
|
+
}
|
|
637
|
+
: undefined;
|
|
638
|
+
// Lookup leg — match-by → items_page rules → 0/1/2+ branch.
|
|
639
|
+
const lookup = await lookupMatches({
|
|
640
|
+
client,
|
|
641
|
+
boardId: parsed.board,
|
|
642
|
+
metadata: meta.metadata,
|
|
643
|
+
matchBy: matchByEntries,
|
|
644
|
+
onColumnNotFound,
|
|
645
|
+
});
|
|
646
|
+
const decision = decideBranch({
|
|
647
|
+
lookup,
|
|
648
|
+
boardId: parsed.board,
|
|
649
|
+
matchBy: matchByEntries,
|
|
650
|
+
});
|
|
651
|
+
if (decision.kind === 'ambiguous') {
|
|
652
|
+
throw decision.error;
|
|
653
|
+
}
|
|
654
|
+
const sourceAgg = new SourceAggregator({
|
|
655
|
+
source: meta.source,
|
|
656
|
+
cacheAgeSeconds: meta.cacheAgeSeconds,
|
|
657
|
+
});
|
|
658
|
+
// Lookup is always live (items_page never caches); the
|
|
659
|
+
// metadata leg may have been cache-served. The resolver may
|
|
660
|
+
// have refreshed; that's already folded into meta via
|
|
661
|
+
// `mergeSource`-style logic below.
|
|
662
|
+
sourceAgg.record('live', null);
|
|
663
|
+
// Filter-warnings → envelope warnings. The resolver fires
|
|
664
|
+
// collision + stale_cache_refreshed; both surface on the
|
|
665
|
+
// success envelope.
|
|
666
|
+
const lookupWarnings = lookup.warnings;
|
|
667
|
+
const { dateResolution, peopleResolution } = buildResolutionContexts({ client, ctx, globalFlags });
|
|
668
|
+
if (decision.kind === 'create') {
|
|
669
|
+
await runCreateBranch({
|
|
670
|
+
client,
|
|
671
|
+
boardId: parsed.board,
|
|
672
|
+
name: parsed.name,
|
|
673
|
+
setEntries,
|
|
674
|
+
rawEntries,
|
|
675
|
+
createLabelsIfMissing: parsed.createLabelsIfMissing,
|
|
676
|
+
dateResolution,
|
|
677
|
+
peopleResolution,
|
|
678
|
+
env: ctx.env,
|
|
679
|
+
noCache: globalFlags.noCache,
|
|
680
|
+
dryRun: globalFlags.dryRun,
|
|
681
|
+
ctx,
|
|
682
|
+
programOpts: program.opts(),
|
|
683
|
+
apiVersion,
|
|
684
|
+
toEmit,
|
|
685
|
+
sourceAgg,
|
|
686
|
+
lookupWarnings,
|
|
687
|
+
matchBy: matchByEntries,
|
|
688
|
+
});
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
await runUpdateBranch({
|
|
692
|
+
client,
|
|
693
|
+
boardId: parsed.board,
|
|
694
|
+
itemId: decision.itemId,
|
|
695
|
+
name: parsed.name,
|
|
696
|
+
setEntries,
|
|
697
|
+
rawEntries,
|
|
698
|
+
createLabelsIfMissing: parsed.createLabelsIfMissing,
|
|
699
|
+
dateResolution,
|
|
700
|
+
peopleResolution,
|
|
701
|
+
env: ctx.env,
|
|
702
|
+
noCache: globalFlags.noCache,
|
|
703
|
+
dryRun: globalFlags.dryRun,
|
|
704
|
+
ctx,
|
|
705
|
+
programOpts: program.opts(),
|
|
706
|
+
apiVersion,
|
|
707
|
+
toEmit,
|
|
708
|
+
sourceAgg,
|
|
709
|
+
lookupWarnings,
|
|
710
|
+
matchBy: matchByEntries,
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
},
|
|
714
|
+
};
|
|
715
|
+
const matchByTokenList = (matchBy) => matchBy.map((e) => e.token);
|
|
716
|
+
const runCreateBranch = async (inputs) => {
|
|
717
|
+
if (inputs.dryRun) {
|
|
718
|
+
// Reuse the M9 dry-run engine so the diff cells match `item
|
|
719
|
+
// create` byte-for-byte; then post-process the planned change to
|
|
720
|
+
// hoist `name` + add the upsert-specific match_by / matched_count
|
|
721
|
+
// echoes per cli-design §6.4 upsert shape.
|
|
722
|
+
const result = await planCreate({
|
|
723
|
+
client: inputs.client,
|
|
724
|
+
mode: { kind: 'item', boardId: inputs.boardId },
|
|
725
|
+
name: inputs.name,
|
|
726
|
+
setEntries: inputs.setEntries,
|
|
727
|
+
...(inputs.rawEntries.length === 0
|
|
728
|
+
? {}
|
|
729
|
+
: { rawEntries: inputs.rawEntries }),
|
|
730
|
+
dateResolution: inputs.dateResolution,
|
|
731
|
+
peopleResolution: inputs.peopleResolution,
|
|
732
|
+
env: inputs.env,
|
|
733
|
+
noCache: inputs.noCache,
|
|
734
|
+
});
|
|
735
|
+
const plan = result.plannedChanges[0];
|
|
736
|
+
/* c8 ignore next 6 — defensive: planCreate returns exactly one
|
|
737
|
+
PlannedChange for an item create; the index guard exists for
|
|
738
|
+
narrowing only. */
|
|
739
|
+
if (plan === undefined) {
|
|
740
|
+
throw new ApiError('internal_error', 'upsert create-branch dry-run: planCreate returned zero plannedChanges');
|
|
741
|
+
}
|
|
742
|
+
const planned = {
|
|
743
|
+
operation: 'create_item',
|
|
744
|
+
board_id: plan.board_id,
|
|
745
|
+
name: plan.name,
|
|
746
|
+
resolved_ids: plan.resolved_ids,
|
|
747
|
+
diff: plan.diff,
|
|
748
|
+
match_by: matchByTokenList(inputs.matchBy),
|
|
749
|
+
matched_count: 0,
|
|
750
|
+
};
|
|
751
|
+
// Fold the upsert preflight legs (metadata + lookup) into the
|
|
752
|
+
// dry-run source — `meta.source` must reflect EVERY wire leg that
|
|
753
|
+
// fired, not just planCreate's. The metadata leg may be cache or
|
|
754
|
+
// live; the lookup is always live (items_page never caches), so
|
|
755
|
+
// the aggregate is at minimum 'live' (or 'mixed' if metadata
|
|
756
|
+
// hit cache). Codex round-1 F2.
|
|
757
|
+
const preflight = inputs.sourceAgg.result();
|
|
758
|
+
const dryRunSource = mergeSourceWithPreflight(result.source, preflight.source);
|
|
759
|
+
const dryRunCacheAge = mergeCacheAge(result.cacheAgeSeconds, preflight.cacheAgeSeconds);
|
|
760
|
+
emitDryRun({
|
|
761
|
+
ctx: inputs.ctx,
|
|
762
|
+
programOpts: inputs.programOpts,
|
|
763
|
+
plannedChanges: [planned],
|
|
764
|
+
source: dryRunSource,
|
|
765
|
+
cacheAgeSeconds: dryRunCacheAge,
|
|
766
|
+
warnings: [...inputs.lookupWarnings, ...result.warnings],
|
|
767
|
+
apiVersion: inputs.apiVersion,
|
|
768
|
+
});
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
// Live create branch — three-pass resolution, bundle into
|
|
772
|
+
// column_values, single round-trip create_item.
|
|
773
|
+
const resolutionResult = await resolveAndTranslate({
|
|
774
|
+
client: inputs.client,
|
|
775
|
+
boardId: inputs.boardId,
|
|
776
|
+
setEntries: inputs.setEntries,
|
|
777
|
+
rawEntries: inputs.rawEntries,
|
|
778
|
+
dateResolution: inputs.dateResolution,
|
|
779
|
+
peopleResolution: inputs.peopleResolution,
|
|
780
|
+
env: inputs.env,
|
|
781
|
+
noCache: inputs.noCache,
|
|
782
|
+
});
|
|
783
|
+
const collectedWarnings = [
|
|
784
|
+
...resolutionResult.warnings,
|
|
785
|
+
];
|
|
786
|
+
const resolvedIds = resolutionResult.resolvedIds;
|
|
787
|
+
if (resolutionResult.source !== undefined) {
|
|
788
|
+
inputs.sourceAgg.record(resolutionResult.source, resolutionResult.cacheAgeSeconds);
|
|
789
|
+
}
|
|
790
|
+
const translated = resolutionResult.translated;
|
|
791
|
+
const columnValues = translated.length === 0 ? null : bundleColumnValues(translated);
|
|
792
|
+
let mutationResult;
|
|
793
|
+
try {
|
|
794
|
+
mutationResult = await executeCreate({
|
|
795
|
+
client: inputs.client,
|
|
796
|
+
boardId: inputs.boardId,
|
|
797
|
+
itemName: inputs.name,
|
|
798
|
+
columnValues,
|
|
799
|
+
createLabelsIfMissing: inputs.createLabelsIfMissing,
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
catch (err) {
|
|
803
|
+
/* c8 ignore next 24 — the false arm of `instanceof MondayCliError`
|
|
804
|
+
only fires for raw JS-runtime errors (TypeError, RangeError);
|
|
805
|
+
defensive across all four mutation surfaces (create / update /
|
|
806
|
+
clear / upsert), pattern proven via foldAndRemap unit tests. */
|
|
807
|
+
if (err instanceof MondayCliError) {
|
|
808
|
+
// Same column-archived remap shape `item create` uses (M9 P1).
|
|
809
|
+
// Cache-sourced resolution + Monday rejecting as
|
|
810
|
+
// validation_failed → check live archived state. Pass every
|
|
811
|
+
// translated column id (M5b finding #3) so multi-`--set` cases
|
|
812
|
+
// where a later target is archived still remap.
|
|
813
|
+
throw await foldAndRemap({
|
|
814
|
+
err,
|
|
815
|
+
warnings: [
|
|
816
|
+
...inputs.lookupWarnings.flatMap((w) => w.code === 'column_token_collision' ||
|
|
817
|
+
w.code === 'stale_cache_refreshed'
|
|
818
|
+
? [w]
|
|
819
|
+
: []),
|
|
820
|
+
...collectedWarnings,
|
|
821
|
+
],
|
|
822
|
+
client: inputs.client,
|
|
823
|
+
boardId: inputs.boardId,
|
|
824
|
+
columnIds: translated.map((t) => t.columnId),
|
|
825
|
+
env: inputs.env,
|
|
826
|
+
noCache: inputs.noCache,
|
|
827
|
+
// Defensive fallback: resolveAndTranslate returns a defined
|
|
828
|
+
// source whenever any --set / --set-raw leg fires. The
|
|
829
|
+
// fallback covers the contrived empty-resolution case.
|
|
830
|
+
resolutionSource: resolutionResult.source ?? 'live',
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
throw err;
|
|
834
|
+
}
|
|
835
|
+
// Mutation leg fires live; record so cache-served metadata + live
|
|
836
|
+
// wire calls collapses to `mixed`. Mirrors `item create`'s tail
|
|
837
|
+
// record pattern.
|
|
838
|
+
inputs.sourceAgg.record('live', null);
|
|
839
|
+
const data = {
|
|
840
|
+
...mutationResult.projected,
|
|
841
|
+
operation: 'create_item',
|
|
842
|
+
};
|
|
843
|
+
emitMutation({
|
|
844
|
+
ctx: inputs.ctx,
|
|
845
|
+
data,
|
|
846
|
+
schema: itemUpsertCommand.outputSchema,
|
|
847
|
+
programOpts: inputs.programOpts,
|
|
848
|
+
warnings: [...inputs.lookupWarnings, ...collectedWarnings],
|
|
849
|
+
...inputs.toEmit(mutationResult.response),
|
|
850
|
+
...inputs.sourceAgg.result(),
|
|
851
|
+
resolvedIds,
|
|
852
|
+
});
|
|
853
|
+
};
|
|
854
|
+
const runUpdateBranch = async (inputs) => {
|
|
855
|
+
if (inputs.dryRun) {
|
|
856
|
+
// Reuse the M5b dry-run engine. planChanges produces the
|
|
857
|
+
// `change_*` wire-name on the resulting plannedChange; we
|
|
858
|
+
// override to the verb-level `update_item` per cli-design §6.4
|
|
859
|
+
// upsert shape and add the M12 echoes.
|
|
860
|
+
const result = await planChanges({
|
|
861
|
+
client: inputs.client,
|
|
862
|
+
boardId: inputs.boardId,
|
|
863
|
+
itemId: inputs.itemId,
|
|
864
|
+
setEntries: inputs.setEntries,
|
|
865
|
+
...(inputs.rawEntries.length === 0
|
|
866
|
+
? {}
|
|
867
|
+
: { rawEntries: inputs.rawEntries }),
|
|
868
|
+
nameChange: inputs.name,
|
|
869
|
+
dateResolution: inputs.dateResolution,
|
|
870
|
+
peopleResolution: inputs.peopleResolution,
|
|
871
|
+
env: inputs.env,
|
|
872
|
+
noCache: inputs.noCache,
|
|
873
|
+
});
|
|
874
|
+
const plan = result.plannedChanges[0];
|
|
875
|
+
/* c8 ignore next 6 — defensive: planChanges returns exactly one
|
|
876
|
+
PlannedChange for a single-item plan; the guard exists for
|
|
877
|
+
narrowing only. */
|
|
878
|
+
if (plan === undefined) {
|
|
879
|
+
throw new ApiError('internal_error', 'upsert update-branch dry-run: planChanges returned zero plannedChanges');
|
|
880
|
+
}
|
|
881
|
+
const planned = {
|
|
882
|
+
operation: 'update_item',
|
|
883
|
+
board_id: plan.board_id,
|
|
884
|
+
item_id: plan.item_id,
|
|
885
|
+
name: inputs.name,
|
|
886
|
+
resolved_ids: plan.resolved_ids,
|
|
887
|
+
diff: plan.diff,
|
|
888
|
+
match_by: matchByTokenList(inputs.matchBy),
|
|
889
|
+
matched_count: 1,
|
|
890
|
+
};
|
|
891
|
+
// Fold the upsert preflight legs (metadata + lookup) into the
|
|
892
|
+
// dry-run source. planChanges' source is always `'live' |
|
|
893
|
+
// 'cache' | 'mixed'` (no `'none'` arm — it always reads the
|
|
894
|
+
// item state); use mergeSource directly. Codex round-1 F2.
|
|
895
|
+
const preflight = inputs.sourceAgg.result();
|
|
896
|
+
const dryRunSource = mergeSource(preflight.source, result.source);
|
|
897
|
+
const dryRunCacheAge = mergeCacheAge(result.cacheAgeSeconds, preflight.cacheAgeSeconds);
|
|
898
|
+
emitDryRun({
|
|
899
|
+
ctx: inputs.ctx,
|
|
900
|
+
programOpts: inputs.programOpts,
|
|
901
|
+
plannedChanges: [planned],
|
|
902
|
+
source: dryRunSource,
|
|
903
|
+
cacheAgeSeconds: dryRunCacheAge,
|
|
904
|
+
warnings: [...inputs.lookupWarnings, ...result.warnings],
|
|
905
|
+
apiVersion: inputs.apiVersion,
|
|
906
|
+
});
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
// Live update branch — three-pass resolution, then
|
|
910
|
+
// selectMutation + execute. Mirrors item update's single-item path
|
|
911
|
+
// verbatim (Codex round-4 P2: same wire shape, same atomicity).
|
|
912
|
+
const resolutionResult = await resolveAndTranslate({
|
|
913
|
+
client: inputs.client,
|
|
914
|
+
boardId: inputs.boardId,
|
|
915
|
+
setEntries: inputs.setEntries,
|
|
916
|
+
rawEntries: inputs.rawEntries,
|
|
917
|
+
dateResolution: inputs.dateResolution,
|
|
918
|
+
peopleResolution: inputs.peopleResolution,
|
|
919
|
+
env: inputs.env,
|
|
920
|
+
noCache: inputs.noCache,
|
|
921
|
+
});
|
|
922
|
+
const collectedWarnings = [
|
|
923
|
+
...resolutionResult.warnings,
|
|
924
|
+
];
|
|
925
|
+
const resolvedIds = resolutionResult.resolvedIds;
|
|
926
|
+
if (resolutionResult.source !== undefined) {
|
|
927
|
+
inputs.sourceAgg.record(resolutionResult.source, resolutionResult.cacheAgeSeconds);
|
|
928
|
+
}
|
|
929
|
+
const translated = resolutionResult.translated;
|
|
930
|
+
// Synthetic name key — same shape item update's single path uses.
|
|
931
|
+
// selectMutation handles bundling: name-only → simple; name + cols
|
|
932
|
+
// (or ≥2 cols) → multi.
|
|
933
|
+
const allTranslated = [
|
|
934
|
+
{
|
|
935
|
+
columnId: 'name',
|
|
936
|
+
columnType: 'text',
|
|
937
|
+
rawInput: inputs.name,
|
|
938
|
+
payload: { format: 'simple', value: inputs.name },
|
|
939
|
+
resolvedFrom: null,
|
|
940
|
+
peopleResolution: null,
|
|
941
|
+
},
|
|
942
|
+
...translated,
|
|
943
|
+
];
|
|
944
|
+
let mutationResult;
|
|
945
|
+
try {
|
|
946
|
+
const mutation = selectMutation(allTranslated);
|
|
947
|
+
mutationResult = await executeUpdate({
|
|
948
|
+
client: inputs.client,
|
|
949
|
+
mutation,
|
|
950
|
+
itemId: inputs.itemId,
|
|
951
|
+
boardId: inputs.boardId,
|
|
952
|
+
createLabelsIfMissing: inputs.createLabelsIfMissing,
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
catch (err) {
|
|
956
|
+
/* c8 ignore next 21 — the false arm of `instanceof MondayCliError`
|
|
957
|
+
only fires for raw JS-runtime errors; defensive across all four
|
|
958
|
+
mutation surfaces. Pattern proven via foldAndRemap unit tests. */
|
|
959
|
+
if (err instanceof MondayCliError) {
|
|
960
|
+
throw await foldAndRemap({
|
|
961
|
+
err,
|
|
962
|
+
warnings: [
|
|
963
|
+
...inputs.lookupWarnings.flatMap((w) => w.code === 'column_token_collision' ||
|
|
964
|
+
w.code === 'stale_cache_refreshed'
|
|
965
|
+
? [w]
|
|
966
|
+
: []),
|
|
967
|
+
...collectedWarnings,
|
|
968
|
+
],
|
|
969
|
+
client: inputs.client,
|
|
970
|
+
boardId: inputs.boardId,
|
|
971
|
+
columnIds: translated.map((t) => t.columnId),
|
|
972
|
+
env: inputs.env,
|
|
973
|
+
noCache: inputs.noCache,
|
|
974
|
+
// Defensive fallback: resolveAndTranslate returns a defined
|
|
975
|
+
// source whenever any --set / --set-raw leg fires; covers the
|
|
976
|
+
// --name-only update path failing, a contrived edge case.
|
|
977
|
+
resolutionSource: resolutionResult.source ?? 'live',
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
throw err;
|
|
981
|
+
}
|
|
982
|
+
inputs.sourceAgg.record('live', null);
|
|
983
|
+
const data = {
|
|
984
|
+
...mutationResult.projected,
|
|
985
|
+
operation: 'update_item',
|
|
986
|
+
};
|
|
987
|
+
emitMutation({
|
|
988
|
+
ctx: inputs.ctx,
|
|
989
|
+
data,
|
|
990
|
+
schema: itemUpsertCommand.outputSchema,
|
|
991
|
+
programOpts: inputs.programOpts,
|
|
992
|
+
warnings: [...inputs.lookupWarnings, ...collectedWarnings],
|
|
993
|
+
...inputs.toEmit(mutationResult.response),
|
|
994
|
+
...inputs.sourceAgg.result(),
|
|
995
|
+
resolvedIds,
|
|
996
|
+
});
|
|
997
|
+
};
|
|
998
|
+
//# sourceMappingURL=upsert.js.map
|