From 2b49bfbe69d8c664436ec3fab0d414d436d49847 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Mon, 12 Oct 2026 20:14:18 +0500 Subject: [PATCH 1/8] chore: enforce generated SDK quality and contract gates --- .github/workflows/quality.yml | 60 + .gitignore | 10 + .husky/pre-commit | 1 + .nvmrc | 1 + AGENTS.md | 708 +- CMakeLists.txt | 5 +- Config.cmake.in | 5 + eslint.config.mjs | 13 + include/one-msg-sdk/AnyType.h | 2 +- include/one-msg-sdk/ApiClient.h | 7 +- include/one-msg-sdk/ApiConfiguration.h | 2 +- include/one-msg-sdk/ApiException.h | 2 +- include/one-msg-sdk/HttpContent.h | 2 +- include/one-msg-sdk/IHttpBody.h | 2 +- include/one-msg-sdk/JsonBody.h | 2 +- include/one-msg-sdk/ModelBase.h | 2 +- include/one-msg-sdk/MultipartFormData.h | 2 +- include/one-msg-sdk/Object.h | 2 +- include/one-msg-sdk/api/CallingApi.h | 4 +- include/one-msg-sdk/api/CatalogApi.h | 4 +- include/one-msg-sdk/api/ChannelApi.h | 31 +- include/one-msg-sdk/api/FlowsApi.h | 23 +- include/one-msg-sdk/api/GroupsApi.h | 28 +- include/one-msg-sdk/api/MessagingApi.h | 51 +- include/one-msg-sdk/api/ProfileApi.h | 13 +- include/one-msg-sdk/api/TemplatesApi.h | 26 +- include/one-msg-sdk/api/UsersApi.h | 2 +- include/one-msg-sdk/api/WebhooksApi.h | 16 +- .../model/AddTemplate_200_response.h | 96 + .../one-msg-sdk/model/AddTemplate_request.h | 14 +- include/one-msg-sdk/model/BlockUser_request.h | 2 +- include/one-msg-sdk/model/CallingSettings.h | 2 +- .../model/CallingSettings_calling.h | 2 +- .../model/CallingSettings_calling_audio.h | 2 +- .../CallingSettings_calling_call_hours.h | 2 +- .../model/CallingSettings_calling_sip.h | 2 +- ...allingSettings_calling_sip_servers_inner.h | 2 +- .../model/CallingSettings_calling_video.h | 2 +- .../model/ConversationalAutomation.h | 2 +- .../ConversationalAutomation_commands_inner.h | 2 +- .../model/CreateCommerce_200_response.h | 2 +- .../model/CreateCommerce_request.h | 2 +- .../model/CreateCommerce_request_params.h | 2 +- .../one-msg-sdk/model/CreateFlows_request.h | 144 + .../model/CreateGroupsGroupId_request.h | 99 + .../model/CreateGroups_200_response.h | 2 +- .../one-msg-sdk/model/CreateGroups_request.h | 88 + .../model/CreateReadMessage_200_response.h | 2 +- .../model/CreateReadMessage_401_response.h | 2 +- .../model/CreateReadMessage_request.h | 2 +- .../model/CreateSettings_request.h | 134 + .../model/CreateSettings_request_webhookUrl.h | 63 + .../model/CreateUploadMedia_200_response.h | 94 + .../model/CreateUploadMedia_request.h | 88 + .../model/DeleteFlowsFlowId_200_response.h | 2 +- .../model/DeleteGroupsGroupId_200_response.h | 2 +- .../model/DeleteMediaLegacy_request.h | 2 +- include/one-msg-sdk/model/ErrorResponse.h | 2 +- .../model/GetCommerce_200_response_inner.h | 2 +- .../model/GetMmLiteStatus_200_response.h | 2 +- .../model/GetStatus_200_response.h | 132 + .../model/GetWebhook_200_response.h | 149 +- .../GetWebhook_200_response_webhookUrl.h | 63 + ...tWhatsappBusinessEncryption_200_response.h | 2 +- .../one-msg-sdk/model/InitiateCallRequest.h | 2 +- .../model/InitiateCallRequest_session.h | 2 +- .../one-msg-sdk/model/InitiateCallResponse.h | 2 +- .../model/InitiateCallResponse_calls_inner.h | 2 +- .../model/InitiateCallResponse_response.h | 2 +- .../model/ListBlockedUsers_200_response.h | 2 +- .../model/ListFlows_200_response.h | 2 +- .../model/ListMessages_200_response.h | 2 +- .../model/ListSettings_200_response.h | 291 + .../ListSettings_200_response_webhookUrl.h | 63 + .../model/ListTemplates_200_response.h | 2 +- .../one-msg-sdk/model/MessageSentResponse.h | 2 +- .../PatchFlowsFlowIdAssets_200_response.h | 2 +- .../model/PatchFlowsFlowIdAssets_request.h | 78 + .../model/PatchFlowsFlowIdMetadata_request.h | 111 + include/one-msg-sdk/model/ProfileInfo.h | 2 +- .../model/RemoveTemplate_request.h | 77 + .../model/RetrieveMedia_200_response.h | 2 +- .../model/SendAddressMessage_request.h | 2 +- .../one-msg-sdk/model/SendButton_request.h | 52 +- .../model/SendButton_request_sections_inner.h | 2 +- .../SendButton_request_sections_inner_reply.h | 2 +- .../model/SendCarousel_request_1.h | 21 +- .../one-msg-sdk/model/SendContact_request.h | 34 +- .../model/SendContact_request_contact.h | 115 + .../model/SendContact_request_contact_name.h | 63 + .../SendContact_request_contacts_inner.h | 21 +- .../SendContact_request_contacts_inner_name.h | 2 +- .../SendContact_request_contacts_inner_org.h | 2 +- ...tact_request_contacts_inner_phones_inner.h | 5 +- .../one-msg-sdk/model/SendCtaUrl_request.h | 2 +- include/one-msg-sdk/model/SendFileRequest.h | 2 +- .../one-msg-sdk/model/SendFlow_request_1.h | 2 +- .../model/SendFlow_request_1_header.h | 123 +- .../model/SendFlow_request_header.h | 123 +- include/one-msg-sdk/model/SendList_request.h | 24 +- .../model/SendList_request_sections_inner.h | 2 +- ...ndList_request_sections_inner_rows_inner.h | 2 +- .../model/SendLocationRequest_request.h | 24 +- .../model/SendLocation_request_1.h | 2 +- .../one-msg-sdk/model/SendMessageRequest.h | 4 +- .../model/SendOrderDetails_request.h | 2 +- .../model/SendOrderDetails_request_language.h | 2 +- .../model/SendOrderDetails_request_order.h | 2 +- ...ndOrderDetails_request_order_items_inner.h | 2 +- ...Details_request_order_items_inner_amount.h | 2 +- .../model/SendPaymentRequest_request.h | 2 +- .../one-msg-sdk/model/SendProduct_request.h | 157 + .../one-msg-sdk/model/SendReaction_request.h | 16 +- .../one-msg-sdk/model/SendSticker_request.h | 2 +- .../one-msg-sdk/model/SendTemplate_request.h | 43 +- .../model/SendTemplate_request_language.h | 10 +- .../model/SetWebhook_200_response.h | 105 + .../SetWebhook_200_response_webhookUrl.h | 63 + .../one-msg-sdk/model/SetWebhook_request.h | 94 + .../model/SetWebhook_request_webhookUrl.h | 63 + .../SetWhatsappBusinessEncryption_request.h | 2 +- include/one-msg-sdk/model/SuccessResponse.h | 2 +- .../UpdateCallingSettings_200_response.h | 2 +- ...ateCallingSettings_200_response_response.h | 2 +- .../one-msg-sdk/model/UpdateMe_200_response.h | 94 + include/one-msg-sdk/model/UpdateMe_request.h | 13 +- include/one-msg-sdk/model/WebhookUrlStatus.h | 204 + knip.json | 12 + package-lock.json | 15 + package.json | 25 + quality.config.mjs | 14 + quality/CMakeLists.txt | 9 + quality/consumer/CMakeLists.txt | 8 + quality/generator/generate.mjs | 145 + quality/generator/inventory.json | 241 + quality/generator/openapi.yaml | 4621 +++++++++++ quality/generator/provenance.json | 110 + quality/generator/verify-negative.mjs | 59 + quality/postprocess.mjs | 107 + quality/templates/flow-header.h | 63 + quality/tests/contract.cpp | 42 + src/AnyType.cpp | 2 +- src/ApiClient.cpp | 2 +- src/ApiConfiguration.cpp | 2 +- src/ApiException.cpp | 2 +- src/HttpContent.cpp | 2 +- src/JsonBody.cpp | 2 +- src/ModelBase.cpp | 2 +- src/MultipartFormData.cpp | 2 +- src/Object.cpp | 2 +- src/api/CallingApi.cpp | 2 +- src/api/CatalogApi.cpp | 2 +- src/api/ChannelApi.cpp | 305 +- src/api/FlowsApi.cpp | 83 +- src/api/GroupsApi.cpp | 72 +- src/api/MessagingApi.cpp | 112 +- src/api/ProfileApi.cpp | 27 +- src/api/TemplatesApi.cpp | 48 +- src/api/UsersApi.cpp | 2 +- src/api/WebhooksApi.cpp | 27 +- src/model/AddTemplate_200_response.cpp | 171 + src/model/AddTemplate_request.cpp | 2 +- src/model/BlockUser_request.cpp | 2 +- src/model/CallingSettings.cpp | 2 +- src/model/CallingSettings_calling.cpp | 2 +- src/model/CallingSettings_calling_audio.cpp | 2 +- .../CallingSettings_calling_call_hours.cpp | 2 +- src/model/CallingSettings_calling_sip.cpp | 2 +- ...lingSettings_calling_sip_servers_inner.cpp | 2 +- src/model/CallingSettings_calling_video.cpp | 2 +- src/model/ConversationalAutomation.cpp | 2 +- ...onversationalAutomation_commands_inner.cpp | 2 +- src/model/CreateCommerce_200_response.cpp | 2 +- src/model/CreateCommerce_request.cpp | 2 +- src/model/CreateCommerce_request_params.cpp | 2 +- src/model/CreateFlows_request.cpp | 398 + src/model/CreateGroupsGroupId_request.cpp | 221 + src/model/CreateGroups_200_response.cpp | 2 +- src/model/CreateGroups_request.cpp | 172 + src/model/CreateReadMessage_200_response.cpp | 2 +- src/model/CreateReadMessage_401_response.cpp | 2 +- src/model/CreateReadMessage_request.cpp | 2 +- src/model/CreateSettings_request.cpp | 416 + .../CreateSettings_request_webhookUrl.cpp | 2 + src/model/CreateUploadMedia_200_response.cpp | 172 + src/model/CreateUploadMedia_request.cpp | 172 + src/model/DeleteFlowsFlowId_200_response.cpp | 2 +- .../DeleteGroupsGroupId_200_response.cpp | 2 +- src/model/DeleteMediaLegacy_request.cpp | 2 +- src/model/ErrorResponse.cpp | 2 +- src/model/GetCommerce_200_response_inner.cpp | 2 +- src/model/GetMmLiteStatus_200_response.cpp | 2 +- src/model/GetStatus_200_response.cpp | 370 + src/model/GetWebhook_200_response.cpp | 615 +- .../GetWebhook_200_response_webhookUrl.cpp | 2 + ...hatsappBusinessEncryption_200_response.cpp | 2 +- src/model/InitiateCallRequest.cpp | 2 +- src/model/InitiateCallRequest_session.cpp | 2 +- src/model/InitiateCallResponse.cpp | 2 +- .../InitiateCallResponse_calls_inner.cpp | 2 +- src/model/InitiateCallResponse_response.cpp | 2 +- src/model/ListBlockedUsers_200_response.cpp | 2 +- src/model/ListFlows_200_response.cpp | 2 +- src/model/ListMessages_200_response.cpp | 2 +- src/model/ListSettings_200_response.cpp | 1053 +++ .../ListSettings_200_response_webhookUrl.cpp | 2 + src/model/ListTemplates_200_response.cpp | 2 +- src/model/MessageSentResponse.cpp | 2 +- .../PatchFlowsFlowIdAssets_200_response.cpp | 2 +- src/model/PatchFlowsFlowIdAssets_request.cpp | 122 + .../PatchFlowsFlowIdMetadata_request.cpp | 302 + src/model/ProfileInfo.cpp | 2 +- src/model/RemoveTemplate_request.cpp | 123 + src/model/RetrieveMedia_200_response.cpp | 2 +- src/model/SendAddressMessage_request.cpp | 2 +- src/model/SendButton_request.cpp | 196 +- .../SendButton_request_sections_inner.cpp | 2 +- ...endButton_request_sections_inner_reply.cpp | 2 +- src/model/SendCarousel_request_1.cpp | 50 +- src/model/SendContact_request.cpp | 148 +- src/model/SendContact_request_contact.cpp | 317 + .../SendContact_request_contact_name.cpp | 2 + .../SendContact_request_contacts_inner.cpp | 26 +- ...endContact_request_contacts_inner_name.cpp | 2 +- ...SendContact_request_contacts_inner_org.cpp | 2 +- ...ct_request_contacts_inner_phones_inner.cpp | 2 +- src/model/SendCtaUrl_request.cpp | 2 +- src/model/SendFileRequest.cpp | 2 +- src/model/SendFlow_request_1.cpp | 2 +- src/model/SendFlow_request_1_header.cpp | 71 +- src/model/SendFlow_request_header.cpp | 71 +- src/model/SendList_request.cpp | 100 +- src/model/SendList_request_sections_inner.cpp | 2 +- ...List_request_sections_inner_rows_inner.cpp | 2 +- src/model/SendLocationRequest_request.cpp | 100 +- src/model/SendLocation_request_1.cpp | 2 +- src/model/SendMessageRequest.cpp | 2 +- src/model/SendOrderDetails_request.cpp | 2 +- .../SendOrderDetails_request_language.cpp | 2 +- src/model/SendOrderDetails_request_order.cpp | 2 +- ...OrderDetails_request_order_items_inner.cpp | 2 +- ...tails_request_order_items_inner_amount.cpp | 2 +- src/model/SendPaymentRequest_request.cpp | 2 +- src/model/SendProduct_request.cpp | 471 ++ src/model/SendReaction_request.cpp | 51 +- src/model/SendSticker_request.cpp | 2 +- src/model/SendTemplate_request.cpp | 108 +- src/model/SendTemplate_request_language.cpp | 2 +- src/model/SetWebhook_200_response.cpp | 220 + .../SetWebhook_200_response_webhookUrl.cpp | 2 + src/model/SetWebhook_request.cpp | 171 + src/model/SetWebhook_request_webhookUrl.cpp | 2 + .../SetWhatsappBusinessEncryption_request.cpp | 2 +- src/model/SuccessResponse.cpp | 2 +- .../UpdateCallingSettings_200_response.cpp | 2 +- ...eCallingSettings_200_response_response.cpp | 2 +- src/model/UpdateMe_200_response.cpp | 172 + src/model/UpdateMe_request.cpp | 2 +- src/model/WebhookUrlStatus.cpp | 613 ++ tools/quality/README.md | 85 + tools/quality/eslint.mjs | 137 + tools/quality/lib/baseline.mjs | 82 + tools/quality/lib/git.mjs | 86 + tools/quality/lib/guards.mjs | 356 + tools/quality/lib/historical.mjs | 139 + tools/quality/lib/knip-reporter.mjs | 42 + tools/quality/lib/reports.mjs | 265 + tools/quality/lib/template.mjs | 56 + tools/quality/package-lock.json | 6852 +++++++++++++++++ tools/quality/package.json | 34 + tools/quality/prettier.config.mjs | 2 + tools/quality/run.mjs | 360 + tools/quality/seal.mjs | 19 + tools/quality/template-manifest.json | 25 + tools/quality/test/cli.test.mjs | 510 ++ tools/quality/test/ratchet.test.mjs | 238 + tools/quality/tsconfig.next.json | 16 + tools/quality/tsconfig.node.json | 13 + tools/quality/tsconfig.svelte.json | 14 + 279 files changed, 25869 insertions(+), 1362 deletions(-) create mode 100644 .github/workflows/quality.yml create mode 100644 .husky/pre-commit create mode 100644 .nvmrc create mode 100644 eslint.config.mjs create mode 100644 include/one-msg-sdk/model/AddTemplate_200_response.h create mode 100644 include/one-msg-sdk/model/CreateFlows_request.h create mode 100644 include/one-msg-sdk/model/CreateGroupsGroupId_request.h create mode 100644 include/one-msg-sdk/model/CreateGroups_request.h create mode 100644 include/one-msg-sdk/model/CreateSettings_request.h create mode 100644 include/one-msg-sdk/model/CreateSettings_request_webhookUrl.h create mode 100644 include/one-msg-sdk/model/CreateUploadMedia_200_response.h create mode 100644 include/one-msg-sdk/model/CreateUploadMedia_request.h create mode 100644 include/one-msg-sdk/model/GetStatus_200_response.h create mode 100644 include/one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h create mode 100644 include/one-msg-sdk/model/ListSettings_200_response.h create mode 100644 include/one-msg-sdk/model/ListSettings_200_response_webhookUrl.h create mode 100644 include/one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h create mode 100644 include/one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h create mode 100644 include/one-msg-sdk/model/RemoveTemplate_request.h create mode 100644 include/one-msg-sdk/model/SendContact_request_contact.h create mode 100644 include/one-msg-sdk/model/SendContact_request_contact_name.h create mode 100644 include/one-msg-sdk/model/SendProduct_request.h create mode 100644 include/one-msg-sdk/model/SetWebhook_200_response.h create mode 100644 include/one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h create mode 100644 include/one-msg-sdk/model/SetWebhook_request.h create mode 100644 include/one-msg-sdk/model/SetWebhook_request_webhookUrl.h create mode 100644 include/one-msg-sdk/model/UpdateMe_200_response.h create mode 100644 include/one-msg-sdk/model/WebhookUrlStatus.h create mode 100644 knip.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 quality.config.mjs create mode 100644 quality/CMakeLists.txt create mode 100644 quality/consumer/CMakeLists.txt create mode 100644 quality/generator/generate.mjs create mode 100644 quality/generator/inventory.json create mode 100644 quality/generator/openapi.yaml create mode 100644 quality/generator/provenance.json create mode 100644 quality/generator/verify-negative.mjs create mode 100644 quality/postprocess.mjs create mode 100644 quality/templates/flow-header.h create mode 100644 quality/tests/contract.cpp create mode 100644 src/model/AddTemplate_200_response.cpp create mode 100644 src/model/CreateFlows_request.cpp create mode 100644 src/model/CreateGroupsGroupId_request.cpp create mode 100644 src/model/CreateGroups_request.cpp create mode 100644 src/model/CreateSettings_request.cpp create mode 100644 src/model/CreateSettings_request_webhookUrl.cpp create mode 100644 src/model/CreateUploadMedia_200_response.cpp create mode 100644 src/model/CreateUploadMedia_request.cpp create mode 100644 src/model/GetStatus_200_response.cpp create mode 100644 src/model/GetWebhook_200_response_webhookUrl.cpp create mode 100644 src/model/ListSettings_200_response.cpp create mode 100644 src/model/ListSettings_200_response_webhookUrl.cpp create mode 100644 src/model/PatchFlowsFlowIdAssets_request.cpp create mode 100644 src/model/PatchFlowsFlowIdMetadata_request.cpp create mode 100644 src/model/RemoveTemplate_request.cpp create mode 100644 src/model/SendContact_request_contact.cpp create mode 100644 src/model/SendContact_request_contact_name.cpp create mode 100644 src/model/SendProduct_request.cpp create mode 100644 src/model/SetWebhook_200_response.cpp create mode 100644 src/model/SetWebhook_200_response_webhookUrl.cpp create mode 100644 src/model/SetWebhook_request.cpp create mode 100644 src/model/SetWebhook_request_webhookUrl.cpp create mode 100644 src/model/UpdateMe_200_response.cpp create mode 100644 src/model/WebhookUrlStatus.cpp create mode 100644 tools/quality/README.md create mode 100644 tools/quality/eslint.mjs create mode 100644 tools/quality/lib/baseline.mjs create mode 100644 tools/quality/lib/git.mjs create mode 100644 tools/quality/lib/guards.mjs create mode 100644 tools/quality/lib/historical.mjs create mode 100644 tools/quality/lib/knip-reporter.mjs create mode 100644 tools/quality/lib/reports.mjs create mode 100644 tools/quality/lib/template.mjs create mode 100644 tools/quality/package-lock.json create mode 100644 tools/quality/package.json create mode 100644 tools/quality/prettier.config.mjs create mode 100644 tools/quality/run.mjs create mode 100644 tools/quality/seal.mjs create mode 100644 tools/quality/template-manifest.json create mode 100644 tools/quality/test/cli.test.mjs create mode 100644 tools/quality/test/ratchet.test.mjs create mode 100644 tools/quality/tsconfig.next.json create mode 100644 tools/quality/tsconfig.node.json create mode 100644 tools/quality/tsconfig.svelte.json diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..740beeb --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,60 @@ +name: Quality +on: + pull_request: + push: + branches: [main] +permissions: + contents: read +concurrency: + group: quality-${{ github.ref }} + cancel-in-progress: true +jobs: + contract: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: "24.19.0" + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "24" + - run: npm ci + - run: npm --prefix tools/quality ci + - run: node --test tools/quality/test/*.test.mjs + - run: node tools/quality/run.mjs guards + - run: npm run format:check + - run: npm run lint:static + - run: npm run lint:unused:production + - run: npm run lint:unused:full + - run: npm run lint:duplicates + - run: npm run lint:duplicates:full + - run: node quality/generator/generate.mjs + - run: node quality/generator/verify-negative.mjs + - run: sudo apt-get update && sudo apt-get install -y libcpprest-dev libboost-all-dev cmake ninja-build + - run: cmake -S quality -B .quality-build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 + - run: cmake --build .quality-build --parallel 2 + - run: ctest --test-dir .quality-build --output-on-failure + - run: cmake --install .quality-build/sdk --prefix "${{ runner.temp }}/sdk-install" + - run: cmake -S quality/consumer -B .quality-build/consumer -DCMAKE_PREFIX_PATH="${{ runner.temp }}/sdk-install" + - run: cmake --build .quality-build/consumer --parallel 2 + - run: ctest --test-dir .quality-build/consumer --output-on-failure + - uses: actions/upload-artifact@v4 + if: always() + with: + name: quality-evidence + path: | + quality/generator/provenance.json + quality/generator/inventory.json + quality/reports/ + quality-required: + if: always() + needs: [contract] + runs-on: ubuntu-24.04 + steps: + - env: + RESULTS: ${{ toJSON(needs) }} + run: node -e 'const jobs=JSON.parse(process.env.RESULTS); if(!Object.values(jobs).every(job=>job.result==="success")) process.exit(1)' diff --git a/.gitignore b/.gitignore index 4581ef2..cf27d35 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,13 @@ *.exe *.out *.app + +.quality-build/ + +node_modules/ +quality/reports/ + +.husky/_/ + +# Local shared-tool dependency links are never repository content. +tools/quality/node_modules diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..81e401a --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +node tools/quality/node_modules/lint-staged/bin/lint-staged.js diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..60ade1a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24.19.0 diff --git a/AGENTS.md b/AGENTS.md index d7af765..524482c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,707 +1,11 @@ -# AGENTS.md — one-msg-sdk +# SDK quality contract -> **Purpose:** exhaustive machine-readable integration guide for AI coding agents. -> **Human docs:** [README.md](./README.md) +This repository implements profile D of 1MSG-156. `cpp` is the native SDK language; JavaScript rules apply only to authored generator/check tooling. The SDK maintainers own the public generated model/API surface and offline contract fixtures. -## Identity +`quality/generator/openapi.yaml` is pinned to the upstream revision and input hashes in `provenance.json`. OpenAPI Generator 7.22.0 is downloaded with a verified SHA256. Update the contract and its provenance deliberately, then run `node quality/generator/generate.mjs --write`; never hand-edit generated outputs. Every generated code path is replayed and hashed in a temporary directory. New, removed, ignored and modified generated files must match the inventory. Compatibility repairs belong in `quality/postprocess.mjs` and the corresponding upstream producer. -```yaml -package: "one-msg-sdk" -registry: https://github.com/1msg/1msg-sdk-cpp -repository: https://github.com/1msg/1msg-sdk-cpp -language: C++ -version: 1.0.1 -public_only: true -never_mention: chat-api -``` +Use Node 24.19.0 for tooling and `npm --prefix tools/quality ci`. Run `node tools/quality/run.mjs guards`, `node tools/quality/node_modules/eslint/bin/eslint.js . --max-warnings=0`, `node --test tools/quality/test/*.test.mjs`, generation replay, and the native commands in `.github/workflows/quality.yml`. Native contract fixtures use local transports/serialization only; no live API credentials are needed. Comments describe intent, invariants, failure cases and resource ownership on new/changed functions. -## Decision tree - -```text -Need WhatsApp messaging from C++? - └─ yes → git clone github.com/1msg/1msg-sdk-cpp + CMake - └─ MessagingApi with host = baseUrl/instanceId - ├─ text reply → sendMessage(token, body, chatId|phone) - ├─ file/media → sendFile / uploadMedia - ├─ template (24h closed) → sendTemplate - ├─ interactive list/buttons → sendList / sendButton - ├─ read inbox → listMessages - ├─ profile → getMe - ├─ groups → GroupsApi.* - ├─ flows → FlowsApi.* - └─ templates list → listTemplates -``` - -## Auth invariants - -1. Base path is `{baseUrl}/{instanceId}` (no trailing slash issues). -2. URL: `https://{baseUrl}/{instanceId}/{path}?token={token}`. -3. Pass channel token as the first arg to generated methods. -4. Never log, commit, or expose tokens. -5. Server-side only — no browser usage. - -## Client map - -```cpp -MessagingApi -ProfileApi -GroupsApi -FlowsApi -TemplatesApi -ChannelApi -CallingApi -WebhooksApi -``` - -## Recipient rules - -- `chatId`: `12020721369@c.us` (1:1) or `...@g.us` (group) -- `phone`: country code + number, no `+` -- Exactly one of `chatId` | `phone` per request - -## Anti-patterns - -- ❌ Raw HTTP without token query param -- ❌ Hardcoding token in source -- ❌ Using sendMessage when 24h window is closed (use sendTemplate) -- ❌ Referencing internal `chat-api` repo name in user-facing code - -## Operation catalog - -### getCallingSettings - -```yaml -operationId: getCallingSettings -http: GET /callingSettings -clientGroup: calling -summary: Get calling settings -description: Return WhatsApp Calling API settings for this channel (beta). Proxies upstream `GET /calling/settings`. **Prerequisites** - Number must be eligible for Meta Calling (Cloud API; not COEX) - Trial / `subscriptionBlocked` channels receive **403** plain text - You need your own WebRTC or SIP stack; 1msg is a **signaling proxy** only and does **not** store call history or recordings See the **Calling** tag overview for inbound/outbound flows and webhooks. -responses: 200, 401, 500 -``` - -### initiateCall - -```yaml -operationId: initiateCall -http: POST /initiateCall -clientGroup: calling -summary: Call action (connect / pre_accept / accept / reject / terminate) -description: Perform a WhatsApp Calling action (beta). Proxies upstream `POST /calling/calls`. Despite the historical path name `/initiateCall`, this endpoint handles **all** call actions: | action | Use | Required | |--------|-----|----------| | `connect` | Outbound business → user | `to` + `session` (`sdp_type: offer`) | | `pre_accept` | Inbound (optional, reduces audio clipping) | `call_id` + `session` (`sdp_type: answer`) | | `accept` | Inbound answer | `call_id` + `session` (`sdp_type: answer`) | | `reject` | Decline inbound | `call_id` | | `terminate` | Hang up | `call_id` | **SDP / media (critical)** - `accept` / `pre_accept` require a **WebRTC-generated SDP answer**. - Do **not** send Meta's offer SDP back as the answer. - Postman (or curl) alone **cannot** establish real media — you need a WebRTC or SIP stack. 1msg only proxies signaling. Answer within ~**30–60 seconds** of an inbound `connect` webhook or Meta terminates as unanswered. Common Meta errors include Calling not enabled (`138000`), no permission (`138006`), SDP validation failures. **Outbound** requires a prior Call Permission Request (CPR) acceptance. See the **Calling** tag overview for the full outbound flow and CPR limits. Trial / `subscriptionBlocked` → **403** plain text. Upstream failures often return HTTP 200 with `{ "response": { "error": "..." } }`. -responses: 200, 401, 500 -``` - -### updateCallingSettings - -```yaml -operationId: updateCallingSettings -http: POST /callingSettings -clientGroup: calling -summary: Update calling settings -description: Enable, disable, or update WhatsApp Calling settings (beta). Proxies upstream `POST /calling/settings`. Body is forwarded as-is (1msg does not validate fields). **Common fields under `calling`** - `status` (`ENABLED` | `DISABLED`) — required to turn calling on/off - `call_icon_visibility` (`DEFAULT` | `DISABLE_ALL`) — optional - `callback_permission_status` (`ENABLED` | `DISABLED`) — optional; when enabled, inbound user calls grant callback permission - `call_hours` — optional hours / timezone object - `sip` — optional SIP trunk; when SIP is ENABLED, Graph call actions and calling webhooks are not used - `srtp_key_exchange_protocol` (`DTLS` | `SDES`) — SDES only with SIP - `video.status` — optional Meta may accept only one feature group per request — prefer focused updates (e.g. enable status first, then SIP). Trial / `subscriptionBlocked` → **403** plain text. -responses: 200, 401, 500 -``` - -### createCommerce - -```yaml -operationId: createCommerce -http: POST /commerce -clientGroup: catalog -summary: Set Commerce Settings -description: Update catalog/cart commerce settings via the `params` object. - `params.is_catalog_visible` — show catalog storefront icon (`true`) or hide it (`false`). - `params.is_cart_enabled` — enable cart (`true`) or disable it (`false`). Blocked when the channel subscription limit is exceeded. Requires a commerce-capable channel (Cloud Functions `/commerceWAV2`). -responses: 200, 401, 500 -``` - -### getCommerce - -```yaml -operationId: getCommerce -http: GET /commerce -clientGroup: catalog -summary: Get Commerce Settings -description: Returns catalog/cart commerce settings for the channel. - `is_catalog_visible` — show catalog storefront icon (`true`) or hide it (`false`). - `is_cart_enabled` — enable cart (`true`) or disable it (`false`). -responses: 200, 401, 500 -``` - -### getConversationalAutomation - -```yaml -operationId: getConversationalAutomation -http: GET /conversationalAutomation -clientGroup: channel -summary: Get conversational automation settings -description: Get WhatsApp conversational components for the channel (welcome message, ice-breaker prompts, and slash commands). Proxies Meta/360dialog `GET /conversational_automation`. When `enable_welcome_message` is true and a user opens chat for the first time, Meta delivers a webhook message with `type: request_welcome`. The inbound formatter exposes that as `type: "request_welcome"` and `meta.request_welcome: true` so your webhook can send a custom welcome reply. -responses: 200, 401, 500 -``` - -### getStatus - -```yaml -operationId: getStatus -http: GET /status -clientGroup: channel -summary: Get channel status -description: Returns WhatsApp Business API client connection status. -responses: 200, 401, 500 -``` - -### setConversationalAutomation - -```yaml -operationId: setConversationalAutomation -http: POST /conversationalAutomation -clientGroup: channel -summary: Set conversational automation settings -description: Update WhatsApp conversational components. Allowed body fields (others are ignored): - `enable_welcome_message` (boolean) - `prompts` (string[], max 4, each ≤ 80 chars) - `commands` (`{ command_name, command_description }[]`) Proxies Meta/360dialog `POST /conversational_automation`. -responses: 200, 401, 500 -``` - -### createFlows - -```yaml -operationId: createFlows -http: POST /flows -clientGroup: flows -summary: Create Flow -responses: 200 -``` - -### createFlowsFlowIdDeprecate - -```yaml -operationId: createFlowsFlowIdDeprecate -http: POST /flows/{flowId}/deprecate -clientGroup: flows -summary: Deprecate Flow -responses: 200 -``` - -### createFlowsFlowIdPublish - -```yaml -operationId: createFlowsFlowIdPublish -http: POST /flows/{flowId}/publish -clientGroup: flows -summary: Publish Flow -responses: 200 -``` - -### deleteFlowsFlowId - -```yaml -operationId: deleteFlowsFlowId -http: DELETE /flows/{flowId} -clientGroup: flows -summary: Delete Flow -responses: 200 -``` - -### getFlowsFlowId - -```yaml -operationId: getFlowsFlowId -http: GET /flows/{flowId} -clientGroup: flows -summary: Get Flow Details -responses: 200 -``` - -### getFlowsFlowIdPreview - -```yaml -operationId: getFlowsFlowIdPreview -http: GET /flows/{flowId}/preview -clientGroup: flows -summary: Preview Flow -responses: 200 -``` - -### getWhatsappBusinessEncryption - -```yaml -operationId: getWhatsappBusinessEncryption -http: GET /whatsapp_business_encryption -clientGroup: flows -summary: Get business encryption public key -description: Retrieve the WhatsApp business public key and signature status for this channel's phone number. Required before publishing or sending Flows that use data encryption. -responses: 200, 401, 500 -``` - -### listFlows - -```yaml -operationId: listFlows -http: GET /flows -clientGroup: flows -summary: List Flows -responses: 200 -``` - -### patchFlowsFlowIdAssets - -```yaml -operationId: patchFlowsFlowIdAssets -http: PATCH /flows/{flowId}/assets -clientGroup: flows -summary: Update Flow Structure -responses: 200 -``` - -### patchFlowsFlowIdMetadata - -```yaml -operationId: patchFlowsFlowIdMetadata -http: PATCH /flows/{flowId}/metadata -clientGroup: flows -summary: Update Flow Metadata -responses: 200 -``` - -### setWhatsappBusinessEncryption - -```yaml -operationId: setWhatsappBusinessEncryption -http: POST /whatsapp_business_encryption -clientGroup: flows -summary: Set business encryption public key -description: Upload and sign a 2048-bit RSA business public key (PEM) for this channel's phone number. Meta requires a signed key before Flow publish/send. Only one active key per number; a new upload replaces the previous key. -responses: 200, 400, 401, 500 -``` - -### createGroups - -```yaml -operationId: createGroups -http: POST /groups -clientGroup: groups -summary: Create Group -responses: 200 -``` - -### createGroupsGroupId - -```yaml -operationId: createGroupsGroupId -http: POST /groups/{groupId} -clientGroup: groups -summary: Update Group Info -responses: 200 -``` - -### createGroupsGroupIdInvitelink - -```yaml -operationId: createGroupsGroupIdInvitelink -http: POST /groups/{groupId}/inviteLink -clientGroup: groups -summary: Reset Invite Link -responses: 200 -``` - -### deleteGroupsGroupId - -```yaml -operationId: deleteGroupsGroupId -http: DELETE /groups/{groupId} -clientGroup: groups -summary: Delete Group -responses: 200 -``` - -### getGroupsGroupId - -```yaml -operationId: getGroupsGroupId -http: GET /groups/{groupId} -clientGroup: groups -summary: Get Group Info -responses: 200 -``` - -### getGroupsGroupIdInvitelink - -```yaml -operationId: getGroupsGroupIdInvitelink -http: GET /groups/{groupId}/inviteLink -clientGroup: groups -summary: Get Invite Link -responses: 200 -``` - -### listGroups - -```yaml -operationId: listGroups -http: GET /groups -clientGroup: groups -summary: Get Groups List -responses: 200 -``` - -### createReadMessage - -```yaml -operationId: createReadMessage -http: POST /readMessage -clientGroup: messaging -summary: Mark message as read -responses: 200, 401 -``` - -### createUploadMedia - -```yaml -operationId: createUploadMedia -http: POST /uploadMedia -clientGroup: messaging -summary: Upload media -responses: 200 -``` - -### deleteMedia - -```yaml -operationId: deleteMedia -http: DELETE /media/{mediaId} -clientGroup: messaging -summary: Delete media from WABA storage -description: Delete previously uploaded media by numeric `mediaId` (from `/uploadMedia`). This is the canonical deletion endpoint and uses the REST `DELETE` verb on the media resource path. The older `POST /deleteMedia` is a deprecated alias. -responses: 200, 400, 401, 500 -``` - -### deleteMediaLegacy - -```yaml -operationId: deleteMediaLegacy -http: POST /deleteMedia -clientGroup: messaging -summary: Delete media from WABA storage (deprecated alias) -description: **Deprecated.** Use `DELETE /media/{mediaId}` instead. This POST alias is kept for backward compatibility with earlier integrations. New integrations should call `DELETE /media/{mediaId}`: 1msg follows REST conventions for resource deletion going forward (delete a resource with the `DELETE` verb on its resource path). -responses: 200, 400, 401, 500 -``` - -### getMmLiteStatus - -```yaml -operationId: getMmLiteStatus -http: GET /mmLiteStatus -clientGroup: messaging -summary: Get MM Lite availability and status -responses: 200, 401, 500 -``` - -### listMessages - -```yaml -operationId: listMessages -http: GET /messages -clientGroup: messaging -summary: Get messages list -responses: 200 -``` - -### retrieveMedia - -```yaml -operationId: retrieveMedia -http: GET /retrieveMedia -clientGroup: messaging -summary: Retrieve uploaded media metadata -description: Get WABA media URL and metadata by mediaId (from uploadMedia). The returned `url` is temporary and typically expires within ~5 minutes. -responses: 200, 400, 401, 500 -``` - -### sendAddressMessage - -```yaml -operationId: sendAddressMessage -http: POST /sendAddressMessage -clientGroup: messaging -summary: Send address request message -description: Request shipping address from the user (WhatsApp interactive `address_message`). **India and Singapore only.** Requires: - Business WhatsApp number registered in that country - Recipient phone matching the country (`+91` ↔ `IN`, `+65` ↔ `SG`) Pass `country: "IN"` or `country: "SG"`. Eligibility is validated upstream; mismatches (e.g. Singapore phone with `country: "IN"`) return errors such as `Unsupported Interactive Message type` (HTTP 200 with `sent: false`). Optional action parameters: `values`, `saved_addresses`, `validation_errors`. -responses: 200, 400, 401, 429, 500 -``` - -### sendButton - -```yaml -operationId: sendButton -http: POST /sendButton -clientGroup: messaging -summary: Send Reply Buttons Message -responses: 200, 400, 401, 429, 500 -``` - -### sendCarousel - -```yaml -operationId: sendCarousel -http: POST /sendCarousel -clientGroup: messaging -summary: Send Carousel -description: You can send product cards via Carousel in two ways: Template messages: do not require a 24-hour customer service window between you and the recipient. Use sendTemplate. Free-form messages: can be sent only when a customer service window is open between you and the recipient. Use sendCarousel. The message structure in /sendCarousel is largely similar to sending a template. However, in this case you must explicitly specify all elements that are created in advance when working with templates. This is because the message is sent without using a template. In /sendCarousel, for sending a Catalog Carousel there can be either 1 URL button or one or more quick reply buttons. -responses: 200, 400, 401, 429, 500 -``` - -### sendContact - -```yaml -operationId: sendContact -http: POST /sendContact -clientGroup: messaging -summary: Send a Contact -responses: 200, 400, 401, 429, 500 -``` - -### sendCtaUrl - -```yaml -operationId: sendCtaUrl -http: POST /sendCtaUrl -clientGroup: messaging -summary: Send CTA URL interactive message -description: Send an interactive message with a single call-to-action URL button. -responses: 200, 400, 401, 429, 500 -``` - -### sendFile - -```yaml -operationId: sendFile -http: POST /sendFile -clientGroup: messaging -summary: Send a File -description: Send a file to an existing chat. (Only if the dialogue has an Open Session). Only one of two parameters is needed to determine the destination - chatId or phone. -responses: 200, 400, 401, 429, 500 -``` - -### sendFlow - -```yaml -operationId: sendFlow -http: POST /sendFlow -clientGroup: messaging -summary: Send WhatsApp Flow Message -description: Send Interactive WhatsApp Flow message to an existing chat. (Only if the dialogue has an Open Session). Only one of two parameters is needed to determine the destination - chatId or phone. Use this method to send a published WhatsApp Flow as a service (interactive) message. If the 24-hour window is closed, send a template with a FLOW button via /sendTemplate. -responses: 200, 400, 401, 429, 500 -``` - -### sendList - -```yaml -operationId: sendList -http: POST /sendList -clientGroup: messaging -summary: Send List Message -responses: 200, 400, 401, 429, 500 -``` - -### sendLocation - -```yaml -operationId: sendLocation -http: POST /sendLocation -clientGroup: messaging -summary: Send a Location -description: Send a location to an existing chat. (Only if the dialogue has an Open Session). Only one of two parameters is needed to determine the destination - chatId or phone. -responses: 200, 400, 401, 429, 500 -``` - -### sendLocationRequest - -```yaml -operationId: sendLocationRequest -http: POST /sendLocationRequest -clientGroup: messaging -summary: Send Location Request Message -responses: 200, 400, 401, 429, 500 -``` - -### sendMessage - -```yaml -operationId: sendMessage -http: POST /sendMessage -clientGroup: messaging -summary: Send a Message -description: Send a message to an existing chat. (Only if the dialogue has an Open Session). The message will be added to the queue for sending and delivered even if the phone is disconnected from the Internet or authorization is not passed. Only one of two parameters is needed to determine the destination - chatId or phone. -responses: 200, 400, 401, 429, 500 -``` - -### sendOrderDetails - -```yaml -operationId: sendOrderDetails -http: POST /sendOrderDetails -clientGroup: messaging -summary: Send order details (India payments template) -description: Send a WhatsApp **order details** payment / invoice message using a pre-approved **Utility** template that has an `ORDER_DETAILS` button. **India only** (WhatsApp Payments India). Requires: - India WhatsApp Business number - Commerce enabled on the channel (`GET`/`POST /commerce`) - Approved template with an `ORDER_DETAILS` button Use this method when you need structured fields (`order`, `referenceId`, `currency`, `paymentSettings`). The API appends a template button `sub_type: order_details` and sends via the same path as `POST /sendTemplate`. Works **outside the 24-hour session window** (template message). You can also send the same payload yourself with `POST /sendTemplate` by including a button component in `params`: ```json { "type": "button", "sub_type": "order_details", "index": 0, "parameters": [{ "type": "action", "action": { "order_details": { "reference_id": "order-123", "currency": "INR", "order": { "status": "pending", "items": [], "subtotal": { "offset": 100, "value": 50000 } } } } }] } ``` -responses: 200, 400, 401, 500 -``` - -### sendPaymentRequest - -```yaml -operationId: sendPaymentRequest -http: POST /sendPaymentRequest -clientGroup: messaging -summary: Send payment request (regional) -description: Send a regional payment request interactive message (beta scaffold). `region` must be IN, SG, or BR. Payload shape follows Meta regional payments docs; verify on stage before production use. Full regional builders are not implemented yet. -responses: 200, 400, 401, 500 -``` - -### sendProduct - -```yaml -operationId: sendProduct -http: POST /sendProduct -clientGroup: messaging -summary: Send a Product -responses: 200, 400, 401, 429, 500 -``` - -### sendReaction - -```yaml -operationId: sendReaction -http: POST /sendReaction -clientGroup: messaging -summary: Send Reaction -responses: 200, 400, 401, 429, 500 -``` - -### sendSticker - -```yaml -operationId: sendSticker -http: POST /sendSticker -clientGroup: messaging -summary: Send sticker message -description: Send a WhatsApp sticker by mediaId or link URL. -responses: 200, 400, 401, 429, 500 -``` - -### getMe - -```yaml -operationId: getMe -http: GET /me -clientGroup: profile -summary: Get Profile Info -description: Get WhatsApp Business Account profile information -responses: 200, 401, 500 -``` - -### updateMe - -```yaml -operationId: updateMe -http: POST /me -clientGroup: profile -summary: Update profile info -description: Update WhatsApp Business Account profile fields. At least one of about, description, email, photo, address, vertical, websites is required. Blocked when the channel subscription limit is exceeded. -responses: 200, 401, 422, 500 -``` - -### addTemplate - -```yaml -operationId: addTemplate -http: POST /addTemplate -clientGroup: templates -summary: Create message template -responses: 200, 401, 500 -``` - -### listTemplates - -```yaml -operationId: listTemplates -http: GET /templates -clientGroup: templates -summary: Get templates list -responses: 200 -``` - -### removeTemplate - -```yaml -operationId: removeTemplate -http: POST /removeTemplate -clientGroup: templates -summary: Remove message template -responses: 200, 401, 500 -``` - -### sendTemplate - -```yaml -operationId: sendTemplate -http: POST /sendTemplate -clientGroup: templates -summary: Send Template Message -description: Send a WhatsApp template message (works outside the 24-hour session window). Supported `params` button `sub_type` values include: `url`, `quick_reply`, `copy_code` / `coupon_code`, `catalog`, `flow`, `limited_time_offer`, and **`order_details`** (WhatsApp Payments **India only** — requires an approved Utility template with an ORDER_DETAILS button). For India order/invoice payments outside 24h, include a button component: ```json { "type": "button", "sub_type": "order_details", "index": 0, "parameters": [{ "type": "action", "action": { "order_details": { "reference_id": "...", "currency": "INR", "order": {} } } }] } ``` Convenience wrapper with structured fields: `POST /sendOrderDetails`. -responses: 200 -``` - -### blockUser - -```yaml -operationId: blockUser -http: POST /blockUser -clientGroup: users -summary: Block WhatsApp user -responses: 200, 400, 401, 500 -``` - -### listBlockedUsers - -```yaml -operationId: listBlockedUsers -http: GET /blockedUsers -clientGroup: users -summary: List blocked WhatsApp users -description: Returns users currently blocked on this WhatsApp channel (WABA `GET /block_users`). Same channel token auth as `blockUser` / `unblockUser`. -responses: 200, 401, 500 -``` - -### unblockUser - -```yaml -operationId: unblockUser -http: POST /unblockUser -clientGroup: users -summary: Unblock WhatsApp user -responses: 200, 400, 401, 500 -``` - -### getWebhook - -```yaml -operationId: getWebhook -http: GET /webhook -clientGroup: webhooks -summary: Get webhook URL -description: Returns the configured client webhook URL for this channel. -responses: 200, 401, 500 -``` - -### setWebhook - -```yaml -operationId: setWebhook -http: POST /webhook -clientGroup: webhooks -summary: Set webhook URL -description: Configure the client webhook URL for inbound events. WhatsApp **Calling** events (`field=calls`) are forwarded as passthrough payloads with `type: "calls"` and `instanceId` (connect / status / terminate). Call permission replies arrive on the normal messages path (`call_permission_reply`). Details: **Calling** tag. -responses: 200, 401, 500 -``` - -## Metadata - -openapi_title: 1MSG WhatsApp Business API (Public) -openapi_version: 1.0.0 -operations: 60 -package: one-msg-sdk -registry: Git / CMake +The `quality-required` aggregate fails if any required job is failed, skipped or cancelled. Repository branch protection must require that check; a workflow file alone does not configure GitHub protection. No generation/build/publish command may swallow errors. +`tools/quality` is a checksum-sealed versioned vendor preset, validated by its own executable tests and integrity check; Knip analyzes the consumer tooling graph and excludes that nested vendor workspace. `java` is the explicitly provisioned native generator runtime (CI Temurin24), not an npm package; its pinned generator JAR checksum is mandatory. No authored consumer source is excluded. diff --git a/CMakeLists.txt b/CMakeLists.txt index 52126df..f7a47d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # # 1MSG WhatsApp Business API (Public) -# Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ +# Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ # # The version of the OpenAPI document: 1.0.0 # @@ -38,6 +38,7 @@ endif() find_package(cpprestsdk REQUIRED) target_compile_definitions(cpprestsdk::cpprest INTERFACE _TURN_OFF_PLATFORM_STRING) find_package(Boost REQUIRED) +find_package(OpenSSL REQUIRED) include(GNUInstallDirs) include(CMakePackageConfigHelpers) @@ -59,7 +60,7 @@ target_include_directories(${PROJECT_NAME} $ ) -target_link_libraries(${PROJECT_NAME} PUBLIC Boost::headers cpprestsdk::cpprest) +target_link_libraries(${PROJECT_NAME} PUBLIC Boost::headers cpprestsdk::cpprest OpenSSL::SSL OpenSSL::Crypto) configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" diff --git a/Config.cmake.in b/Config.cmake.in index 9015c2b..b5db02c 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -1,5 +1,10 @@ @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) +find_dependency(Boost) +find_dependency(cpprestsdk) +find_dependency(OpenSSL) + include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake) check_required_components("@PROJECT_NAME@") diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..b3efe8c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,13 @@ +import { staticConfig, globals } from "./tools/quality/eslint.mjs"; +export default [ + { + ignores: [ + "**/node_modules/**", + "tools/quality/**", + "vendor/**", + ".build/**", + ".quality-build/**", + ], + }, + ...staticConfig({ globals: globals.node }), +]; diff --git a/include/one-msg-sdk/AnyType.h b/include/one-msg-sdk/AnyType.h index 3eaae51..4edc1e7 100644 --- a/include/one-msg-sdk/AnyType.h +++ b/include/one-msg-sdk/AnyType.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/ApiClient.h b/include/one-msg-sdk/ApiClient.h index fbd87c2..92fd1f8 100644 --- a/include/one-msg-sdk/ApiClient.h +++ b/include/one-msg-sdk/ApiClient.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -64,6 +64,11 @@ class ApiClient static utility::string_t parameterToString(const utility::datetime &value); static utility::string_t parameterToString(bool value); static utility::string_t parameterToString(const ModelBase& value); + // 1MSG: map form values use generated JSON serializers. + template + static utility::string_t parameterToString(const std::map& value) { + return ModelBase::toJson(value).serialize(); + } template static utility::string_t parameterToString(const std::vector& value); template diff --git a/include/one-msg-sdk/ApiConfiguration.h b/include/one-msg-sdk/ApiConfiguration.h index de86896..5031723 100644 --- a/include/one-msg-sdk/ApiConfiguration.h +++ b/include/one-msg-sdk/ApiConfiguration.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/ApiException.h b/include/one-msg-sdk/ApiException.h index 6916fd7..c469f2b 100644 --- a/include/one-msg-sdk/ApiException.h +++ b/include/one-msg-sdk/ApiException.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/HttpContent.h b/include/one-msg-sdk/HttpContent.h index 91a7136..b2c053a 100644 --- a/include/one-msg-sdk/HttpContent.h +++ b/include/one-msg-sdk/HttpContent.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/IHttpBody.h b/include/one-msg-sdk/IHttpBody.h index ec12db1..cb34e0b 100644 --- a/include/one-msg-sdk/IHttpBody.h +++ b/include/one-msg-sdk/IHttpBody.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/JsonBody.h b/include/one-msg-sdk/JsonBody.h index 2d1ad3d..b39cf8c 100644 --- a/include/one-msg-sdk/JsonBody.h +++ b/include/one-msg-sdk/JsonBody.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/ModelBase.h b/include/one-msg-sdk/ModelBase.h index be752e8..11af79a 100644 --- a/include/one-msg-sdk/ModelBase.h +++ b/include/one-msg-sdk/ModelBase.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/MultipartFormData.h b/include/one-msg-sdk/MultipartFormData.h index 1e2904c..3cb521f 100644 --- a/include/one-msg-sdk/MultipartFormData.h +++ b/include/one-msg-sdk/MultipartFormData.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/Object.h b/include/one-msg-sdk/Object.h index 04d8635..8efeb41 100644 --- a/include/one-msg-sdk/Object.h +++ b/include/one-msg-sdk/Object.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/api/CallingApi.h b/include/one-msg-sdk/api/CallingApi.h index ab88863..1947ffb 100644 --- a/include/one-msg-sdk/api/CallingApi.h +++ b/include/one-msg-sdk/api/CallingApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -61,7 +61,7 @@ class CallingApi /// Call action (connect / pre_accept / accept / reject / terminate) /// /// - /// Perform a WhatsApp Calling action (beta). Proxies upstream `POST /calling/calls`. Despite the historical path name `/initiateCall`, this endpoint handles **all** call actions: | action | Use | Required | |--------|-----|----------| | `connect` | Outbound business → user | `to` + `session` (`sdp_type: offer`) | | `pre_accept` | Inbound (optional, reduces audio clipping) | `call_id` + `session` (`sdp_type: answer`) | | `accept` | Inbound answer | `call_id` + `session` (`sdp_type: answer`) | | `reject` | Decline inbound | `call_id` | | `terminate` | Hang up | `call_id` | **SDP / media (critical)** - `accept` / `pre_accept` require a **WebRTC-generated SDP answer**. - Do **not** send Meta's offer SDP back as the answer. - Postman (or curl) alone **cannot** establish real media — you need a WebRTC or SIP stack. 1msg only proxies signaling. Answer within ~**30–60 seconds** of an inbound `connect` webhook or Meta terminates as unanswered. Common Meta errors include Calling not enabled (`138000`), no permission (`138006`), SDP validation failures. **Outbound** requires a prior Call Permission Request (CPR) acceptance. See the **Calling** tag overview for the full outbound flow and CPR limits. Trial / `subscriptionBlocked` → **403** plain text. Upstream failures often return HTTP 200 with `{ \"response\": { \"error\": \"...\" } }`. + /// Perform a WhatsApp Calling action (beta). Proxies upstream `POST /calling/calls`. Despite the historical path name `/initiateCall`, this endpoint handles **all** call actions: | action | Use | Required | |--------|-----|----------| | `connect` | Outbound business → user | `to` + `session` (`sdp_type: offer`) | | `pre_accept` | Inbound (optional, reduces audio clipping) | `call_id` + `session` (`sdp_type: answer`) | | `accept` | Inbound answer | `call_id` + `session` (`sdp_type: answer`) | | `reject` | Decline inbound | `call_id` | | `terminate` | Hang up | `call_id` | **SDP / media (critical)** - `accept` / `pre_accept` require a **WebRTC-generated SDP answer**. - Do **not** send Meta's offer SDP back as the answer. - Postman (or curl) alone **cannot** establish real media — you need a WebRTC or SIP stack. 1msg only proxies signaling. Answer within ~**30–60 seconds** of an inbound `connect` webhook or Meta terminates as unanswered. Common Meta errors include Calling not enabled (`138000`), no permission (`138006`), SDP validation failures. **Outbound** requires a prior Call Permission Request (CPR) acceptance. See the **Calling** tag overview for the full outbound flow and CPR limits. Trial / `subscriptionBlocked` → **403** plain text. Upstream failures often return HTTP 200 with `{ \"response\": { \"error\": \"<upstream message>\" } }`. `Invalid API KEY` is used only when Meta/360 body actually indicates an invalid API key or token. Other upstream 401s (notably call permission `138006`) pass through `error.message` / `error_user_msg`. /// /// JWT token or API key for authorization /// diff --git a/include/one-msg-sdk/api/CatalogApi.h b/include/one-msg-sdk/api/CatalogApi.h index 574e1e4..aa20c10 100644 --- a/include/one-msg-sdk/api/CatalogApi.h +++ b/include/one-msg-sdk/api/CatalogApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -63,7 +63,7 @@ class CatalogApi /// Get Commerce Settings /// /// - /// Returns catalog/cart commerce settings for the channel. - `is_catalog_visible` — show catalog storefront icon (`true`) or hide it (`false`). - `is_cart_enabled` — enable cart (`true`) or disable it (`false`). + /// Returns catalog/cart commerce settings for the channel. Fails with a provider error when the WABA has no catalog linked — that is an API/account limitation, not an MCP schema bug. - `is_catalog_visible` — show catalog storefront icon (`true`) or hide it (`false`). - `is_cart_enabled` — enable cart (`true`) or disable it (`false`). /// /// JWT token or API key for authorization pplx::task>> getCommerce( diff --git a/include/one-msg-sdk/api/ChannelApi.h b/include/one-msg-sdk/api/ChannelApi.h index 618ef68..bed2e8c 100644 --- a/include/one-msg-sdk/api/ChannelApi.h +++ b/include/one-msg-sdk/api/ChannelApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -25,7 +25,10 @@ #include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/ConversationalAutomation.h" +#include "one-msg-sdk/model/CreateSettings_request.h" #include "one-msg-sdk/model/ErrorResponse.h" +#include "one-msg-sdk/model/GetStatus_200_response.h" +#include "one-msg-sdk/model/ListSettings_200_response.h" #include #include #include @@ -46,6 +49,18 @@ class ChannelApi virtual ~ChannelApi(); + /// + /// Update channel settings + /// + /// + /// Update channel settings. Only send fields you want to change. `webhookUrl` **replaces** the stored list (one URL string, or up to 5 URLs as an array). Passing an empty value clears webhooks. Repeating the same URL(s) also clears a sticky auto-disable. With several URLs, send the complete array to re-enable one of them — omitting a URL removes it from the channel. + /// + /// JWT token or API key for authorization + /// + pplx::task>> createSettings( + utility::string_t token, + std::shared_ptr createSettingsRequest + ) const; /// /// Get conversational automation settings /// @@ -60,10 +75,20 @@ class ChannelApi /// Get channel status /// /// - /// Returns WhatsApp Business API client connection status. + /// Return WhatsApp Cloud API connection status for this channel (`connected` when the number can send). May include `accountStatus`, messaging limit, and MM Lite availability. Optional `health_status_warning` appears only when Meta Graph health could not be loaded and a soft `connected` response is returned. Omitted on the normal path and when health details are not applicable for the channel — never an internal provider/transport name. + /// + /// JWT token or API key for authorization + pplx::task> getStatus( + utility::string_t token + ) const; + /// + /// Get channel settings + /// + /// + /// Return channel settings: webhook URL(s), delivery flags, and analytics toggles. Auto-disable / circuit state matches `GET /webhook`. **Prefer `webhookStatuses`** (one row per configured URL). The breaker is per URL, not per channel. Channel-level `haveDisabledWebhooks` is `true` when **at least one** URL in `webhookUrl` is sticky auto-disabled — not \"the channel is dead\". Live URLs still receive events. Top-level `circuitState` / `reason` / `fails` / `trips` are a compatibility summary of one URL (first sticky-disabled, else first configured). This is the same `GET /settings` endpoint as the REST API (previously missing from MCP). /// /// JWT token or API key for authorization - pplx::task>> getStatus( + pplx::task> listSettings( utility::string_t token ) const; /// diff --git a/include/one-msg-sdk/api/FlowsApi.h b/include/one-msg-sdk/api/FlowsApi.h index 48b7643..f0dc5d6 100644 --- a/include/one-msg-sdk/api/FlowsApi.h +++ b/include/one-msg-sdk/api/FlowsApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -25,6 +25,7 @@ #include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/CreateCommerce_200_response.h" +#include "one-msg-sdk/model/CreateFlows_request.h" #include "one-msg-sdk/model/CreateGroups_200_response.h" #include "one-msg-sdk/model/CreateReadMessage_401_response.h" #include "one-msg-sdk/model/DeleteFlowsFlowId_200_response.h" @@ -32,6 +33,8 @@ #include "one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h" #include "one-msg-sdk/model/ListFlows_200_response.h" #include "one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h" +#include "one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h" +#include "one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h" #include "one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h" #include #include @@ -57,12 +60,14 @@ class FlowsApi /// Create Flow /// /// - /// + /// Create a WhatsApp Flow (`name` + `categories` required). Currently returns HTTP 501 until the Meta Graph Flows rewrite is available. /// /// JWT token or API key for authorization + /// /// (optional, default to utility::conversions::to_string_t("")) pplx::task> createFlows( utility::string_t token, + std::shared_ptr createFlowsRequest, boost::optional wabaAccountId ) const; /// @@ -149,40 +154,46 @@ class FlowsApi /// List Flows /// /// - /// + /// List WhatsApp Flows for the WABA. Currently returns HTTP 501 until the Meta Graph Flows rewrite is available. /// /// JWT token or API key for authorization /// (optional, default to utility::conversions::to_string_t("")) + /// Comma-separated Flow fields to return (optional, default to utility::conversions::to_string_t("")) pplx::task> listFlows( utility::string_t token, - boost::optional wabaAccountId + boost::optional wabaAccountId, + boost::optional fields ) const; /// /// Update Flow Structure /// /// - /// + /// Replace the Flow JSON document (`flowJson`). Currently returns HTTP 501 until the Meta Graph Flows rewrite is available. /// /// Flow ID /// JWT token or API key for authorization + /// /// (optional, default to utility::conversions::to_string_t("")) pplx::task> patchFlowsFlowIdAssets( utility::string_t flowId, utility::string_t token, + std::shared_ptr patchFlowsFlowIdAssetsRequest, boost::optional wabaAccountId ) const; /// /// Update Flow Metadata /// /// - /// + /// Update Flow `name`, `categories`, and/or `endpointUri`. Currently returns HTTP 501 until the Meta Graph Flows rewrite is available. /// /// Flow ID /// JWT token or API key for authorization + /// /// (optional, default to utility::conversions::to_string_t("")) pplx::task>> patchFlowsFlowIdMetadata( utility::string_t flowId, utility::string_t token, + std::shared_ptr patchFlowsFlowIdMetadataRequest, boost::optional wabaAccountId ) const; /// diff --git a/include/one-msg-sdk/api/GroupsApi.h b/include/one-msg-sdk/api/GroupsApi.h index 08a49d7..1b1598f 100644 --- a/include/one-msg-sdk/api/GroupsApi.h +++ b/include/one-msg-sdk/api/GroupsApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -24,7 +24,9 @@ #include "one-msg-sdk/ApiClient.h" #include "one-msg-sdk/AnyType.h" +#include "one-msg-sdk/model/CreateGroupsGroupId_request.h" #include "one-msg-sdk/model/CreateGroups_200_response.h" +#include "one-msg-sdk/model/CreateGroups_request.h" #include "one-msg-sdk/model/DeleteGroupsGroupId_200_response.h" #include #include @@ -53,20 +55,24 @@ class GroupsApi /// /// /// JWT token or API key for authorization + /// pplx::task> createGroups( - utility::string_t token + utility::string_t token, + std::shared_ptr createGroupsRequest ) const; /// /// Update Group Info /// /// - /// + /// Update group subject, description, and/or profile picture. Path `groupId` is the WABA group id (without `@g.us`). /// /// /// JWT token or API key for authorization + /// pplx::task>> createGroupsGroupId( utility::string_t groupId, - utility::string_t token + utility::string_t token, + std::shared_ptr createGroupsGroupIdRequest ) const; /// /// Reset Invite Link @@ -100,9 +106,11 @@ class GroupsApi /// /// /// JWT token or API key for authorization + /// Comma-separated group fields to return (optional, default to utility::conversions::to_string_t("")) pplx::task>> getGroupsGroupId( utility::string_t groupId, - utility::string_t token + utility::string_t token, + boost::optional fields ) const; /// /// Get Invite Link @@ -120,11 +128,17 @@ class GroupsApi /// Get Groups List /// /// - /// + /// List WhatsApp groups for this channel. Paginate with `limit`, `before`, and `after`. /// /// JWT token or API key for authorization + /// Max groups to return (optional, default to 0) + /// Cursor for the previous page (optional, default to utility::conversions::to_string_t("")) + /// Cursor for the next page (optional, default to utility::conversions::to_string_t("")) pplx::task>> listGroups( - utility::string_t token + utility::string_t token, + boost::optional limit, + boost::optional before, + boost::optional after ) const; protected: diff --git a/include/one-msg-sdk/api/MessagingApi.h b/include/one-msg-sdk/api/MessagingApi.h index 0ceb327..10d8639 100644 --- a/include/one-msg-sdk/api/MessagingApi.h +++ b/include/one-msg-sdk/api/MessagingApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -26,6 +26,8 @@ #include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/CreateReadMessage_200_response.h" #include "one-msg-sdk/model/CreateReadMessage_401_response.h" +#include "one-msg-sdk/model/CreateUploadMedia_200_response.h" +#include "one-msg-sdk/model/CreateUploadMedia_request.h" #include "one-msg-sdk/model/DeleteMediaLegacy_request.h" #include "one-msg-sdk/model/ErrorResponse.h" #include "one-msg-sdk/model/GetMmLiteStatus_200_response.h" @@ -42,6 +44,7 @@ #include "one-msg-sdk/model/SendLocationRequest_request.h" #include "one-msg-sdk/model/SendOrderDetails_request.h" #include "one-msg-sdk/model/SendPaymentRequest_request.h" +#include "one-msg-sdk/model/SendProduct_request.h" #include "one-msg-sdk/model/SendReaction_request.h" #include "one-msg-sdk/model/SendSticker_request.h" #include "one-msg-sdk/model/SuccessResponse.h" @@ -85,13 +88,13 @@ class MessagingApi /// Upload media /// /// - /// + /// Upload a file to WhatsApp media storage and get a numeric `mediaId` for later use with `send_file` / `send_sticker` (`mediaId` field, not `body`). Pass the file as `body` **or** `url` — an HTTP(S) URL or a base64 data URI. The `mediaId` in the response is a numeric string (keep it as a string). /// /// JWT token or API key for authorization - /// (optional) - pplx::task createUploadMedia( + /// + pplx::task> createUploadMedia( utility::string_t token, - boost::optional>> requestBody + std::shared_ptr createUploadMediaRequest ) const; /// /// Delete media from WABA storage @@ -131,11 +134,27 @@ class MessagingApi /// Get messages list /// /// - /// + /// List stored chat history for this channel (requires history storage). Filter with `chatId`, `limit`, `last`, message numbers, or time bounds. /// /// JWT token or API key for authorization + /// Filter messages for one chat (`phone@c.us`, group `@g.us`, or BSUID `@lid`) (optional, default to utility::conversions::to_string_t("")) + /// Max rows to return (default 100) (optional, default to 0) + /// If true, return the latest messages (DESC). Default false. (optional, default to false) + /// (optional, default to 0) + /// (optional, default to 0) + /// Unix timestamp lower bound (optional, default to 0) + /// Unix timestamp upper bound (optional, default to 0) + /// Filter by stored message id (optional, default to utility::conversions::to_string_t("")) pplx::task> listMessages( - utility::string_t token + utility::string_t token, + boost::optional chatId, + boost::optional limit, + boost::optional last, + boost::optional lastMessageNumber, + boost::optional firstMessageNumber, + boost::optional minTime, + boost::optional maxTime, + boost::optional msgId ) const; /// /// Retrieve uploaded media metadata @@ -177,18 +196,20 @@ class MessagingApi /// Send Carousel /// /// - /// You can send product cards via Carousel in two ways: Template messages: do not require a 24-hour customer service window between you and the recipient. Use sendTemplate. Free-form messages: can be sent only when a customer service window is open between you and the recipient. Use sendCarousel. The message structure in /sendCarousel is largely similar to sending a template. However, in this case you must explicitly specify all elements that are created in advance when working with templates. This is because the message is sent without using a template. In /sendCarousel, for sending a Catalog Carousel there can be either 1 URL button or one or more quick reply buttons. + /// You can send product cards via Carousel in two ways: Template messages: do not require a 24-hour customer service window between you and the recipient. Use sendTemplate. Free-form messages: can be sent only when a customer service window is open between you and the recipient. Use sendCarousel. The message structure in /sendCarousel is largely similar to sending a template. However, in this case you must explicitly specify all elements that are created in advance when working with templates. This is because the message is sent without using a template. In /sendCarousel, for a Catalog Carousel there can be either 1 URL button or one or more quick reply buttons. Prefer the simple `cards` array (2–10 cards). Each card needs a header media/product plus a CTA URL or quick-reply buttons. Example: ```json { \"phone\": \"79001234567\", \"body\": \"Pick a product\", \"cards\": [ { \"header\": { \"type\": \"image\", \"image\": { \"link\": \"https://example.com/1.jpg\" } }, \"body\": { \"text\": \"Card one\" }, \"type\": \"cta_url\", \"action\": { \"name\": \"cta_url\", \"parameters\": { \"url\": \"https://example.com/p1\", \"display_text\": \"Open\" } } }, { \"header\": { \"type\": \"image\", \"image\": { \"link\": \"https://example.com/2.jpg\" } }, \"body\": { \"text\": \"Card two\" }, \"type\": \"cta_url\", \"action\": { \"name\": \"cta_url\", \"parameters\": { \"url\": \"https://example.com/p2\", \"display_text\": \"Open\" } } } ] } ``` `params` with a `CAROUSEL` component is the template-like alternative. /// /// JWT token or API key for authorization - /// Required. Template-like structure (same as sendTemplate params). Must include a CAROUSEL component and its cards. Structure: - params[] item with type CAROUSEL and cards (2..10) - cards[] item: - components[] items: - header: parameters[0] with type image/video/product - image: {\\\"image\\\": {\\\"link\\\": \\\"https://...\\\"}} - video: {\\\"video\\\": {\\\"link\\\": \\\"https://...\\\"}} - product: {\\\"product\\\": {\\\"catalog_id\\\": \\\"...\\\", \\\"product_retailer_id\\\": \\\"...\\\"}} - button: sub_type url or quick_reply - url: parameters {\\\"text\\\": \\\"Button\\\", \\\"url\\\": \\\"https://...\\\"} - quick_reply: parameters[] of {\\\"id\\\": \\\"...\\\", \\\"text\\\": \\\"...\\\"} /// Text shown above the carousel. Optional. If omitted and params include a body component, the body will be taken from params. (optional, default to utility::conversions::to_string_t("")) + /// Preferred. 2–10 carousel cards (header + body + CTA or quick replies). (optional, default to std::map<utility::string_t, AnyType>()) + /// Required. Template-like structure (same as sendTemplate params). Must include a CAROUSEL component and its cards. Structure: - params[] item with type CAROUSEL and cards (2..10) - cards[] item: - components[] items: - header: parameters[0] with type image/video/product - image: {\\\"image\\\": {\\\"link\\\": \\\"https://...\\\"}} - video: {\\\"video\\\": {\\\"link\\\": \\\"https://...\\\"}} - product: {\\\"product\\\": {\\\"catalog_id\\\": \\\"...\\\", \\\"product_retailer_id\\\": \\\"...\\\"}} - button: sub_type url or quick_reply - url: parameters {\\\"text\\\": \\\"Button\\\", \\\"url\\\": \\\"https://...\\\"} - quick_reply: parameters[] of {\\\"id\\\": \\\"...\\\", \\\"text\\\": \\\"...\\\"} (optional, default to new Object()) /// Quoted message ID (Cloud API) (optional, default to utility::conversions::to_string_t("")) /// Required if phone is not set. Chat ID from the message list. Examples: 12020721369@c.us or 120363046942338209@g.us(group) (optional, default to utility::conversions::to_string_t("")) /// Required if chatId is not set. A phone number starting with the country code. USA example: 12020721369. (optional, default to 0) pplx::task> sendCarousel( utility::string_t token, - std::vector> params, boost::optional body, + boost::optional>>> cards, + boost::optional>> params, boost::optional quotedMsgId, boost::optional chatId, boost::optional phone @@ -197,7 +218,7 @@ class MessagingApi /// Send a Contact /// /// - /// + /// Send a WhatsApp contact card. Preferred simple body (legacy-compatible): ```json { \"phone\": \"79001234567\", \"contact\": { \"name\": \"Lida\", \"phone\": \"+79181976551\" } } ``` Cloud API shape also works: `contacts` is an array of objects with `name.formatted_name` and `phones[].phone` (E.164 string, **not** a timestamp). /// /// JWT token or API key for authorization /// (optional) @@ -342,7 +363,7 @@ class MessagingApi /// JWT token or API key for authorization /// Message text, UTF-8 or UTF-16 string with emoji /// Message ID to quote/reply to (Cloud API wamid) (optional, default to utility::conversions::to_string_t("")) - /// Chat ID in format: phone@c.us (individual) or phone@g.us (group) (optional, default to utility::conversions::to_string_t("")) + /// Recipient chat ID: phone@c.us, group@g.us, or BSUID@lid (optional, default to utility::conversions::to_string_t("")) /// Phone number starting with country code (alternative to chatId) (optional, default to 0) pplx::task> sendMessage( utility::string_t token, @@ -379,13 +400,13 @@ class MessagingApi /// Send a Product /// /// - /// + /// Send a single catalog product or a product list. Destination is `chatId` or `phone`. `action` is required: - single product: `{ \"catalog_id\": \"...\", \"product_retailer_id\": \"...\" }` - product list: `{ \"catalog_id\": \"...\", \"sections\": [{ \"title\": \"...\", \"product_items\": [{ \"product_retailer_id\": \"...\" }] }] }` /// /// JWT token or API key for authorization - /// (optional) + /// pplx::task> sendProduct( utility::string_t token, - boost::optional>> requestBody + std::shared_ptr sendProductRequest ) const; /// /// Send Reaction diff --git a/include/one-msg-sdk/api/ProfileApi.h b/include/one-msg-sdk/api/ProfileApi.h index 9b51ca4..c1d209f 100644 --- a/include/one-msg-sdk/api/ProfileApi.h +++ b/include/one-msg-sdk/api/ProfileApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -23,11 +23,10 @@ #include "one-msg-sdk/ApiClient.h" -#include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/ErrorResponse.h" #include "one-msg-sdk/model/ProfileInfo.h" +#include "one-msg-sdk/model/UpdateMe_200_response.h" #include "one-msg-sdk/model/UpdateMe_request.h" -#include #include #include @@ -51,7 +50,7 @@ class ProfileApi /// Get Profile Info /// /// - /// Get WhatsApp Business Account profile information + /// Return the WhatsApp Business profile for this channel: About, address, description, email, phone, websites, industry (`vertical`), and profile photo URL. /// /// JWT token or API key for authorization pplx::task> getMe( @@ -64,10 +63,10 @@ class ProfileApi /// Update WhatsApp Business Account profile fields. At least one of about, description, email, photo, address, vertical, websites is required. Blocked when the channel subscription limit is exceeded. /// /// JWT token or API key for authorization - /// (optional) - pplx::task>> updateMe( + /// + pplx::task> updateMe( utility::string_t token, - boost::optional> updateMeRequest + std::shared_ptr updateMeRequest ) const; protected: diff --git a/include/one-msg-sdk/api/TemplatesApi.h b/include/one-msg-sdk/api/TemplatesApi.h index 09fb6e5..ffa54fe 100644 --- a/include/one-msg-sdk/api/TemplatesApi.h +++ b/include/one-msg-sdk/api/TemplatesApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -23,10 +23,12 @@ #include "one-msg-sdk/ApiClient.h" +#include "one-msg-sdk/model/AddTemplate_200_response.h" #include "one-msg-sdk/model/AddTemplate_request.h" #include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/ErrorResponse.h" #include "one-msg-sdk/model/ListTemplates_200_response.h" +#include "one-msg-sdk/model/RemoveTemplate_request.h" #include "one-msg-sdk/model/SendTemplate_request.h" #include #include @@ -52,11 +54,11 @@ class TemplatesApi /// Create message template /// /// - /// + /// Create a WABA message template (`name`, `category`, `language`, `components`). After create, Meta reviews the template; list it with `GET /templates`. /// /// JWT token or API key for authorization /// (optional) - pplx::task>> addTemplate( + pplx::task> addTemplate( utility::string_t token, boost::optional> addTemplateRequest ) const; @@ -64,29 +66,35 @@ class TemplatesApi /// Get templates list /// /// - /// + /// List message templates. Paginate with `limit` / `offset`; sort by `id`, `name`, or `status`. /// /// JWT token or API key for authorization + /// (optional, default to 0) + /// (optional, default to 0) + /// Sort field (`id`, `name`, or `status`) (optional, default to utility::conversions::to_string_t("")) pplx::task> listTemplates( - utility::string_t token + utility::string_t token, + boost::optional limit, + boost::optional offset, + boost::optional sort ) const; /// /// Remove message template /// /// - /// + /// Delete a message template by `name` (all language versions of that name). /// /// JWT token or API key for authorization - /// (optional) + /// pplx::task>> removeTemplate( utility::string_t token, - boost::optional>> requestBody + std::shared_ptr removeTemplateRequest ) const; /// /// Send Template Message /// /// - /// Send a WhatsApp template message (works outside the 24-hour session window). Supported `params` button `sub_type` values include: `url`, `quick_reply`, `copy_code` / `coupon_code`, `catalog`, `flow`, `limited_time_offer`, and **`order_details`** (WhatsApp Payments **India only** — requires an approved Utility template with an ORDER_DETAILS button). For India order/invoice payments outside 24h, include a button component: ```json { \"type\": \"button\", \"sub_type\": \"order_details\", \"index\": 0, \"parameters\": [{ \"type\": \"action\", \"action\": { \"order_details\": { \"reference_id\": \"...\", \"currency\": \"INR\", \"order\": {} } } }] } ``` Convenience wrapper with structured fields: `POST /sendOrderDetails`. + /// Send a WhatsApp **template** message (works outside the 24-hour session window). Use this tool — not `send_message` — when the 24h session is closed. `params` MUST be Cloud API **component objects**, never a flat list of strings and never the old On-Prem `hsm` / `localizable_params` format. Example body variable `{{1}}`: ```json { \"type\": \"body\", \"parameters\": [{ \"type\": \"text\", \"text\": \"Ivan\" }] } ``` Do not send `\"type\": \"hsm\"` and do not send `params: [\"Ivan\", \"123\"]`. Supported `params` button `sub_type` values include: `url`, `quick_reply`, `copy_code` / `coupon_code`, `catalog`, `flow`, `limited_time_offer`, and **`order_details`** (WhatsApp Payments **India only** — requires an approved Utility template with an ORDER_DETAILS button). Convenience wrapper with structured fields: `POST /sendOrderDetails`. /// /// JWT token or API key for authorization /// (optional) diff --git a/include/one-msg-sdk/api/UsersApi.h b/include/one-msg-sdk/api/UsersApi.h index a081b2b..c5379d9 100644 --- a/include/one-msg-sdk/api/UsersApi.h +++ b/include/one-msg-sdk/api/UsersApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/api/WebhooksApi.h b/include/one-msg-sdk/api/WebhooksApi.h index 9d64658..a508a17 100644 --- a/include/one-msg-sdk/api/WebhooksApi.h +++ b/include/one-msg-sdk/api/WebhooksApi.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -23,10 +23,10 @@ #include "one-msg-sdk/ApiClient.h" -#include "one-msg-sdk/AnyType.h" #include "one-msg-sdk/model/ErrorResponse.h" #include "one-msg-sdk/model/GetWebhook_200_response.h" -#include +#include "one-msg-sdk/model/SetWebhook_200_response.h" +#include "one-msg-sdk/model/SetWebhook_request.h" #include #include @@ -50,7 +50,7 @@ class WebhooksApi /// Get webhook URL /// /// - /// Returns the configured client webhook URL for this channel. + /// Return the webhook URL(s) currently configured for this channel, plus delivery status for each URL. `webhookUrl` is a string when a single URL is set, an array of strings when multiple URLs are configured, or `null` if none is set. **Prefer `webhookStatuses`.** The circuit breaker is per URL, not per channel. If 1 of 4 URLs is sticky-disabled, that URL is skipped; the other three still receive events. Send/receive are not affected. Channel-level `haveDisabledWebhooks`, `circuitState`, `reason`, `fails`, `trips`, and timestamps are a compatibility summary of **one** URL (the first sticky-disabled URL, else the first configured URL). They are not \"the channel is dead\". - `haveDisabledWebhooks` — `true` when **at least one** URL in `webhookUrl` is sticky auto-disabled. Live URLs still get events. - `circuitState` — compressed scalar for that same primary URL: `ok` | `degraded` | `open` | `half_open` | `disabled`. - `disabledWebhooks` — currently configured URLs that are sticky-disabled (subset of `webhookUrl`). - `webhookStatuses` — one row per currently configured URL. Use this array to see which endpoints are live vs skipped. - `fails` / `trips` / `firstFailAt` — **diagnostics for support**, not product UI. `fails` = failures in a rolling ~10 minute window (not lifetime). `trips` = failed recovery probes on the 15 min → 1 h → 6 h schedule (sticky disable after 3). Clients can ignore these and use `webhookStatuses` + `disabledWebhooks` only. Sticky disable skips delivery; it does not unconfigure the URL (it stays in `webhookUrl`). Re-enable with `POST /webhook` or `POST /settings`. Those endpoints **replace** the whole list — with multiple URLs, send the full array. /// /// JWT token or API key for authorization pplx::task> getWebhook( @@ -60,13 +60,13 @@ class WebhooksApi /// Set webhook URL /// /// - /// Configure the client webhook URL for inbound events. WhatsApp **Calling** events (`field=calls`) are forwarded as passthrough payloads with `type: \"calls\"` and `instanceId` (connect / status / terminate). Call permission replies arrive on the normal messages path (`call_permission_reply`). Details: **Calling** tag. + /// Set the client webhook URL that receives inbound events for this channel. **Replaces** the stored webhook list (it does not append). To deliver the same events to several endpoints, pass an array in `webhookUrl` (max 5) or use `POST /settings`. With several URLs already configured, posting only the disabled URL **drops the others** — send the complete array to re-enable one of many. Incoming payloads include messages, delivery ACKs, group updates, coexistence echoes, and calling events. WhatsApp Calling payloads (`type: \"calls\"`) are documented under the **Calling** tag. Call permission replies arrive on the normal messages path (`call_permission_reply`). Repeating `POST /webhook` with the same URL(s) clears an auto-disable (self-serve re-enable). Send/receive are not affected by webhook auto-disable. /// /// JWT token or API key for authorization - /// (optional) - pplx::task>> setWebhook( + /// + pplx::task> setWebhook( utility::string_t token, - boost::optional> getWebhook200Response + std::shared_ptr setWebhookRequest ) const; protected: diff --git a/include/one-msg-sdk/model/AddTemplate_200_response.h b/include/one-msg-sdk/model/AddTemplate_200_response.h new file mode 100644 index 0000000..1d09960 --- /dev/null +++ b/include/one-msg-sdk/model/AddTemplate_200_response.h @@ -0,0 +1,96 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * AddTemplate_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_AddTemplate_200_response_H_ +#define ONEMSG_SDK_MODEL_AddTemplate_200_response_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class AddTemplate_200_response + : public ModelBase +{ +public: + AddTemplate_200_response(); + virtual ~AddTemplate_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// AddTemplate_200_response members + + + /// + /// Upstream create-template payload + /// + std::map> getResponse() const; + bool responseIsSet() const; + void unsetResponse(); + void setResponse(const std::map>& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + std::map> m_Response; + bool m_ResponseIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_AddTemplate_200_response_H_ */ diff --git a/include/one-msg-sdk/model/AddTemplate_request.h b/include/one-msg-sdk/model/AddTemplate_request.h index db5c479..56bbafe 100644 --- a/include/one-msg-sdk/model/AddTemplate_request.h +++ b/include/one-msg-sdk/model/AddTemplate_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -58,21 +58,33 @@ class AddTemplate_request /// AddTemplate_request members + /// + /// Template name + /// utility::string_t getName() const; bool nameIsSet() const; void unsetName(); void setName(const utility::string_t& value); + /// + /// MARKETING, UTILITY, or AUTHENTICATION + /// utility::string_t getCategory() const; bool categoryIsSet() const; void unsetCategory(); void setCategory(const utility::string_t& value); + /// + /// Template language code (e.g. en_US) + /// utility::string_t getLanguage() const; bool languageIsSet() const; void unsetLanguage(); void setLanguage(const utility::string_t& value); + /// + /// Template components (HEADER, BODY, FOOTER, BUTTONS, CAROUSEL) + /// std::vector>> getComponents() const; bool componentsIsSet() const; void unsetComponents(); diff --git a/include/one-msg-sdk/model/BlockUser_request.h b/include/one-msg-sdk/model/BlockUser_request.h index 6326fa6..426f6c2 100644 --- a/include/one-msg-sdk/model/BlockUser_request.h +++ b/include/one-msg-sdk/model/BlockUser_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings.h b/include/one-msg-sdk/model/CallingSettings.h index 2890dfc..dd843c9 100644 --- a/include/one-msg-sdk/model/CallingSettings.h +++ b/include/one-msg-sdk/model/CallingSettings.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling.h b/include/one-msg-sdk/model/CallingSettings_calling.h index 6bde38a..82a4d48 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling.h +++ b/include/one-msg-sdk/model/CallingSettings_calling.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling_audio.h b/include/one-msg-sdk/model/CallingSettings_calling_audio.h index 7745029..dbe09d3 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling_audio.h +++ b/include/one-msg-sdk/model/CallingSettings_calling_audio.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling_call_hours.h b/include/one-msg-sdk/model/CallingSettings_calling_call_hours.h index 84a8553..b7527d3 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling_call_hours.h +++ b/include/one-msg-sdk/model/CallingSettings_calling_call_hours.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling_sip.h b/include/one-msg-sdk/model/CallingSettings_calling_sip.h index f8c55ba..5e0c0b8 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling_sip.h +++ b/include/one-msg-sdk/model/CallingSettings_calling_sip.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling_sip_servers_inner.h b/include/one-msg-sdk/model/CallingSettings_calling_sip_servers_inner.h index 84a3a64..f5e3ac0 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling_sip_servers_inner.h +++ b/include/one-msg-sdk/model/CallingSettings_calling_sip_servers_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CallingSettings_calling_video.h b/include/one-msg-sdk/model/CallingSettings_calling_video.h index 8fc718e..9a1e589 100644 --- a/include/one-msg-sdk/model/CallingSettings_calling_video.h +++ b/include/one-msg-sdk/model/CallingSettings_calling_video.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ConversationalAutomation.h b/include/one-msg-sdk/model/ConversationalAutomation.h index 6e99d41..092e831 100644 --- a/include/one-msg-sdk/model/ConversationalAutomation.h +++ b/include/one-msg-sdk/model/ConversationalAutomation.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ConversationalAutomation_commands_inner.h b/include/one-msg-sdk/model/ConversationalAutomation_commands_inner.h index 39a7d32..b020f30 100644 --- a/include/one-msg-sdk/model/ConversationalAutomation_commands_inner.h +++ b/include/one-msg-sdk/model/ConversationalAutomation_commands_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateCommerce_200_response.h b/include/one-msg-sdk/model/CreateCommerce_200_response.h index af72767..1b11f78 100644 --- a/include/one-msg-sdk/model/CreateCommerce_200_response.h +++ b/include/one-msg-sdk/model/CreateCommerce_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateCommerce_request.h b/include/one-msg-sdk/model/CreateCommerce_request.h index 33b06eb..08bf3e8 100644 --- a/include/one-msg-sdk/model/CreateCommerce_request.h +++ b/include/one-msg-sdk/model/CreateCommerce_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateCommerce_request_params.h b/include/one-msg-sdk/model/CreateCommerce_request_params.h index 4e37631..5ae84d6 100644 --- a/include/one-msg-sdk/model/CreateCommerce_request_params.h +++ b/include/one-msg-sdk/model/CreateCommerce_request_params.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateFlows_request.h b/include/one-msg-sdk/model/CreateFlows_request.h new file mode 100644 index 0000000..b507c3f --- /dev/null +++ b/include/one-msg-sdk/model/CreateFlows_request.h @@ -0,0 +1,144 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateFlows_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateFlows_request_H_ +#define ONEMSG_SDK_MODEL_CreateFlows_request_H_ + +#include +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateFlows_request + : public ModelBase +{ +public: + CreateFlows_request(); + virtual ~CreateFlows_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateFlows_request members + + enum class CategoriesEnum + { + SIGN_UP, + SIGN_IN, + APPOINTMENT_BOOKING, + LEAD_GENERATION, + CONTACT_US, + CUSTOMER_SUPPORT, + SURVEY, + OTHER, + }; + /// + /// One or more Flow categories + /// + CategoriesEnum toCategoriesEnum(const utility::string_t& value) const; + const utility::string_t fromCategoriesEnum(const CategoriesEnum value) const; + std::vector toCategoriesEnum(const std::vector& value) const; + std::vector fromCategoriesEnum(const std::vector& value) const; + + + /// + /// Flow name + /// + utility::string_t getName() const; + bool nameIsSet() const; + void unsetName(); + void setName(const utility::string_t& value); + + /// + /// One or more Flow categories + /// + std::vector getCategories() const; + bool categoriesIsSet() const; + void unsetCategories(); + void setCategories(const std::vector value); + + /// + /// HTTPS endpoint for the Flow data channel + /// + utility::string_t getEndpointUri() const; + bool endpointUriIsSet() const; + void unsetEndpointUri(); + void setEndpointUri(const utility::string_t& value); + + /// + /// Publish immediately after create + /// + bool isPublish() const; + bool publishIsSet() const; + void unsetPublish(); + void setPublish(bool value); + + /// + /// Optional Flow JSON document + /// + std::map> getFlowJson() const; + bool flowJsonIsSet() const; + void unsetFlowJson(); + void setFlowJson(const std::map>& value); + + +protected: + utility::string_t m_Name; + bool m_NameIsSet; + + std::vector m_Categories; + bool m_CategoriesIsSet; + + utility::string_t m_EndpointUri; + bool m_EndpointUriIsSet; + + bool m_Publish; + bool m_PublishIsSet; + + std::map> m_FlowJson; + bool m_FlowJsonIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateFlows_request_H_ */ diff --git a/include/one-msg-sdk/model/CreateGroupsGroupId_request.h b/include/one-msg-sdk/model/CreateGroupsGroupId_request.h new file mode 100644 index 0000000..0bf688c --- /dev/null +++ b/include/one-msg-sdk/model/CreateGroupsGroupId_request.h @@ -0,0 +1,99 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateGroupsGroupId_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateGroupsGroupId_request_H_ +#define ONEMSG_SDK_MODEL_CreateGroupsGroupId_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateGroupsGroupId_request + : public ModelBase +{ +public: + CreateGroupsGroupId_request(); + virtual ~CreateGroupsGroupId_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateGroupsGroupId_request members + + + /// + /// New group subject / name + /// + utility::string_t getSubject() const; + bool subjectIsSet() const; + void unsetSubject(); + void setSubject(const utility::string_t& value); + + /// + /// New group description + /// + utility::string_t getDescription() const; + bool descriptionIsSet() const; + void unsetDescription(); + void setDescription(const utility::string_t& value); + + /// + /// Image URL or base64 data URI for the group profile picture + /// + utility::string_t getProfilePictureFile() const; + bool profilePictureFileIsSet() const; + void unsetProfile_picture_file(); + void setProfilePictureFile(const utility::string_t& value); + + +protected: + utility::string_t m_Subject; + bool m_SubjectIsSet; + + utility::string_t m_Description; + bool m_DescriptionIsSet; + + utility::string_t m_Profile_picture_file; + bool m_Profile_picture_fileIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateGroupsGroupId_request_H_ */ diff --git a/include/one-msg-sdk/model/CreateGroups_200_response.h b/include/one-msg-sdk/model/CreateGroups_200_response.h index db124bb..6381de3 100644 --- a/include/one-msg-sdk/model/CreateGroups_200_response.h +++ b/include/one-msg-sdk/model/CreateGroups_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateGroups_request.h b/include/one-msg-sdk/model/CreateGroups_request.h new file mode 100644 index 0000000..1e6e4eb --- /dev/null +++ b/include/one-msg-sdk/model/CreateGroups_request.h @@ -0,0 +1,88 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateGroups_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateGroups_request_H_ +#define ONEMSG_SDK_MODEL_CreateGroups_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateGroups_request + : public ModelBase +{ +public: + CreateGroups_request(); + virtual ~CreateGroups_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateGroups_request members + + + /// + /// Group subject / name + /// + utility::string_t getGroupName() const; + bool groupNameIsSet() const; + void unsetGroupName(); + void setGroupName(const utility::string_t& value); + + /// + /// Optional group description + /// + utility::string_t getDescription() const; + bool descriptionIsSet() const; + void unsetDescription(); + void setDescription(const utility::string_t& value); + + +protected: + utility::string_t m_GroupName; + bool m_GroupNameIsSet; + + utility::string_t m_Description; + bool m_DescriptionIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateGroups_request_H_ */ diff --git a/include/one-msg-sdk/model/CreateReadMessage_200_response.h b/include/one-msg-sdk/model/CreateReadMessage_200_response.h index 8bf71ff..c2a79f4 100644 --- a/include/one-msg-sdk/model/CreateReadMessage_200_response.h +++ b/include/one-msg-sdk/model/CreateReadMessage_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateReadMessage_401_response.h b/include/one-msg-sdk/model/CreateReadMessage_401_response.h index 64a4001..a4a6b58 100644 --- a/include/one-msg-sdk/model/CreateReadMessage_401_response.h +++ b/include/one-msg-sdk/model/CreateReadMessage_401_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateReadMessage_request.h b/include/one-msg-sdk/model/CreateReadMessage_request.h index a0b99d5..74b6f14 100644 --- a/include/one-msg-sdk/model/CreateReadMessage_request.h +++ b/include/one-msg-sdk/model/CreateReadMessage_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/CreateSettings_request.h b/include/one-msg-sdk/model/CreateSettings_request.h new file mode 100644 index 0000000..24f31a5 --- /dev/null +++ b/include/one-msg-sdk/model/CreateSettings_request.h @@ -0,0 +1,134 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateSettings_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateSettings_request_H_ +#define ONEMSG_SDK_MODEL_CreateSettings_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/model/CreateSettings_request_webhookUrl.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateSettings_request + : public ModelBase +{ +public: + CreateSettings_request(); + virtual ~CreateSettings_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateSettings_request members + + + std::shared_ptr getWebhookUrl() const; + bool webhookUrlIsSet() const; + void unsetWebhookUrl(); + void setWebhookUrl(const std::shared_ptr& value); + + bool isGuaranteedHooks() const; + bool guaranteedHooksIsSet() const; + void unsetGuaranteedHooks(); + void setGuaranteedHooks(bool value); + + bool isAckNotificationsOn() const; + bool ackNotificationsOnIsSet() const; + void unsetAckNotificationsOn(); + void setAckNotificationsOn(bool value); + + bool isRawHooks() const; + bool rawHooksIsSet() const; + void unsetRawHooks(); + void setRawHooks(bool value); + + bool isTemplateAnalyticsEnabled() const; + bool templateAnalyticsEnabledIsSet() const; + void unsetTemplate_analytics_enabled(); + void setTemplateAnalyticsEnabled(bool value); + + bool isCtaUrlLinkTrackingOptedOut() const; + bool ctaUrlLinkTrackingOptedOutIsSet() const; + void unsetCta_url_link_tracking_opted_out(); + void setCtaUrlLinkTrackingOptedOut(bool value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + std::shared_ptr m_WebhookUrl; + bool m_WebhookUrlIsSet; + + bool m_GuaranteedHooks; + bool m_GuaranteedHooksIsSet; + + bool m_AckNotificationsOn; + bool m_AckNotificationsOnIsSet; + + bool m_RawHooks; + bool m_RawHooksIsSet; + + bool m_Template_analytics_enabled; + bool m_Template_analytics_enabledIsSet; + + bool m_Cta_url_link_tracking_opted_out; + bool m_Cta_url_link_tracking_opted_outIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateSettings_request_H_ */ diff --git a/include/one-msg-sdk/model/CreateSettings_request_webhookUrl.h b/include/one-msg-sdk/model/CreateSettings_request_webhookUrl.h new file mode 100644 index 0000000..34fa689 --- /dev/null +++ b/include/one-msg-sdk/model/CreateSettings_request_webhookUrl.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class CreateSettings_request_webhookUrl : public ModelBase { +public: + using VariantType = std::variant, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_array()) { std::vector value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/CreateUploadMedia_200_response.h b/include/one-msg-sdk/model/CreateUploadMedia_200_response.h new file mode 100644 index 0000000..dd83296 --- /dev/null +++ b/include/one-msg-sdk/model/CreateUploadMedia_200_response.h @@ -0,0 +1,94 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateUploadMedia_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateUploadMedia_200_response_H_ +#define ONEMSG_SDK_MODEL_CreateUploadMedia_200_response_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateUploadMedia_200_response + : public ModelBase +{ +public: + CreateUploadMedia_200_response(); + virtual ~CreateUploadMedia_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateUploadMedia_200_response members + + + utility::string_t getMediaId() const; + bool mediaIdIsSet() const; + void unsetMediaId(); + void setMediaId(const utility::string_t& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + utility::string_t m_MediaId; + bool m_MediaIdIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateUploadMedia_200_response_H_ */ diff --git a/include/one-msg-sdk/model/CreateUploadMedia_request.h b/include/one-msg-sdk/model/CreateUploadMedia_request.h new file mode 100644 index 0000000..3469570 --- /dev/null +++ b/include/one-msg-sdk/model/CreateUploadMedia_request.h @@ -0,0 +1,88 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * CreateUploadMedia_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_CreateUploadMedia_request_H_ +#define ONEMSG_SDK_MODEL_CreateUploadMedia_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class CreateUploadMedia_request + : public ModelBase +{ +public: + CreateUploadMedia_request(); + virtual ~CreateUploadMedia_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// CreateUploadMedia_request members + + + /// + /// File HTTP(S) URL or base64 data URI (`data:<mime>;base64,...`) + /// + utility::string_t getBody() const; + bool bodyIsSet() const; + void unsetBody(); + void setBody(const utility::string_t& value); + + /// + /// Alias for `body` — public HTTP(S) URL of the file to upload + /// + utility::string_t getUrl() const; + bool urlIsSet() const; + void unsetUrl(); + void setUrl(const utility::string_t& value); + + +protected: + utility::string_t m_Body; + bool m_BodyIsSet; + + utility::string_t m_Url; + bool m_UrlIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_CreateUploadMedia_request_H_ */ diff --git a/include/one-msg-sdk/model/DeleteFlowsFlowId_200_response.h b/include/one-msg-sdk/model/DeleteFlowsFlowId_200_response.h index e4bce6b..92767ff 100644 --- a/include/one-msg-sdk/model/DeleteFlowsFlowId_200_response.h +++ b/include/one-msg-sdk/model/DeleteFlowsFlowId_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/DeleteGroupsGroupId_200_response.h b/include/one-msg-sdk/model/DeleteGroupsGroupId_200_response.h index c9c2d8a..8630a13 100644 --- a/include/one-msg-sdk/model/DeleteGroupsGroupId_200_response.h +++ b/include/one-msg-sdk/model/DeleteGroupsGroupId_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/DeleteMediaLegacy_request.h b/include/one-msg-sdk/model/DeleteMediaLegacy_request.h index 34cbbbd..72e81e3 100644 --- a/include/one-msg-sdk/model/DeleteMediaLegacy_request.h +++ b/include/one-msg-sdk/model/DeleteMediaLegacy_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ErrorResponse.h b/include/one-msg-sdk/model/ErrorResponse.h index f29ee5f..3fe13af 100644 --- a/include/one-msg-sdk/model/ErrorResponse.h +++ b/include/one-msg-sdk/model/ErrorResponse.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/GetCommerce_200_response_inner.h b/include/one-msg-sdk/model/GetCommerce_200_response_inner.h index cf9f3b9..eefc77f 100644 --- a/include/one-msg-sdk/model/GetCommerce_200_response_inner.h +++ b/include/one-msg-sdk/model/GetCommerce_200_response_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/GetMmLiteStatus_200_response.h b/include/one-msg-sdk/model/GetMmLiteStatus_200_response.h index 05585d5..00a40d4 100644 --- a/include/one-msg-sdk/model/GetMmLiteStatus_200_response.h +++ b/include/one-msg-sdk/model/GetMmLiteStatus_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/GetStatus_200_response.h b/include/one-msg-sdk/model/GetStatus_200_response.h new file mode 100644 index 0000000..13c5c9a --- /dev/null +++ b/include/one-msg-sdk/model/GetStatus_200_response.h @@ -0,0 +1,132 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * GetStatus_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_GetStatus_200_response_H_ +#define ONEMSG_SDK_MODEL_GetStatus_200_response_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class GetStatus_200_response + : public ModelBase +{ +public: + GetStatus_200_response(); + virtual ~GetStatus_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// GetStatus_200_response members + + + bool isIsCloud() const; + bool isCloudIsSet() const; + void unsetIsCloud(); + void setIsCloud(bool value); + + /// + /// typically `connected` when the number can send + /// + utility::string_t getStatus() const; + bool statusIsSet() const; + void unsetStatus(); + void setStatus(const utility::string_t& value); + + utility::string_t getAccountStatus() const; + bool accountStatusIsSet() const; + void unsetAccountStatus(); + void setAccountStatus(const utility::string_t& value); + + bool isMmLiteAvailable() const; + bool mmLiteAvailableIsSet() const; + void unsetMm_lite_available(); + void setMmLiteAvailable(bool value); + + /// + /// Optional soft-fail warning when Meta Graph health_status could not be loaded. Never includes internal provider names. + /// + utility::string_t getHealthStatusWarning() const; + bool healthStatusWarningIsSet() const; + void unsetHealth_status_warning(); + void setHealthStatusWarning(const utility::string_t& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + bool m_IsCloud; + bool m_IsCloudIsSet; + + utility::string_t m_Status; + bool m_StatusIsSet; + + utility::string_t m_AccountStatus; + bool m_AccountStatusIsSet; + + bool m_Mm_lite_available; + bool m_Mm_lite_availableIsSet; + + utility::string_t m_Health_status_warning; + bool m_Health_status_warningIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_GetStatus_200_response_H_ */ diff --git a/include/one-msg-sdk/model/GetWebhook_200_response.h b/include/one-msg-sdk/model/GetWebhook_200_response.h index c359124..68bbeef 100644 --- a/include/one-msg-sdk/model/GetWebhook_200_response.h +++ b/include/one-msg-sdk/model/GetWebhook_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -19,14 +19,18 @@ #ifndef ONEMSG_SDK_MODEL_GetWebhook_200_response_H_ #define ONEMSG_SDK_MODEL_GetWebhook_200_response_H_ +#include #include #include "one-msg-sdk/ModelBase.h" #include "one-msg-sdk/AnyType.h" +#include "one-msg-sdk/model/WebhookUrlStatus.h" #include #include #include +#include "one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h" +#include namespace onemsg { namespace sdk { @@ -56,11 +60,114 @@ class GetWebhook_200_response ///////////////////////////////////////////// /// GetWebhook_200_response members + enum class CircuitStateEnum + { + OK, + DEGRADED, + OPEN, + HALF_OPEN, + DISABLED, + }; + /// + /// Compatibility scalar for **one** URL (first sticky-disabled, else first configured). Not the channel as a whole. Prefer `webhookStatuses[].circuitState`. + /// + + CircuitStateEnum toCircuitStateEnum(const utility::string_t& value) const; + const utility::string_t fromCircuitStateEnum(const CircuitStateEnum value) const; - utility::string_t getWebhookUrl() const; + + std::shared_ptr getWebhookUrl() const; bool webhookUrlIsSet() const; void unsetWebhookUrl(); - void setWebhookUrl(const utility::string_t& value); + void setWebhookUrl(const std::shared_ptr& value); + + /// + /// `true` when at least one URL in `webhookUrl` is sticky auto-disabled. Not \"the channel is dead\": other configured URLs still receive events. Send/receive are unaffected. + /// + bool isHaveDisabledWebhooks() const; + bool haveDisabledWebhooksIsSet() const; + void unsetHaveDisabledWebhooks(); + void setHaveDisabledWebhooks(bool value); + + /// + /// Compatibility scalar for **one** URL (first sticky-disabled, else first configured). Not the channel as a whole. Prefer `webhookStatuses[].circuitState`. + /// + CircuitStateEnum getCircuitState() const; + bool circuitStateIsSet() const; + void unsetCircuitState(); + void setCircuitState(const CircuitStateEnum value); + + /// + /// Last qualifying fail reason of the summary URL (same URL as `circuitState`) + /// + utility::string_t getReason() const; + bool reasonIsSet() const; + void unsetReason(); + void setReason(const utility::string_t& value); + + /// + /// Diagnostic only (summary URL). Qualifying failures in the rolling ~10 minute breaker window — not lifetime and not customer retries. Prefer `webhookStatuses` / `disabledWebhooks`. + /// + int32_t getFails() const; + bool failsIsSet() const; + void unsetFails(); + void setFails(int32_t value); + + /// + /// Diagnostic only (summary URL). Failed recovery probes (≈15 min → 1 h → 6 h). Sticky disable after 3. Not a blind unblock timer. + /// + int32_t getTrips() const; + bool tripsIsSet() const; + void unsetTrips(); + void setTrips(int32_t value); + + /// + /// Epoch milliseconds when the summary URL became sticky-disabled + /// + int32_t getDisabledAt() const; + bool disabledAtIsSet() const; + void unsetDisabledAt(); + void setDisabledAt(int32_t value); + + /// + /// Diagnostic only (summary URL). Epoch ms of the first fail in the current ~10 minute window (pairs with `fails`). + /// + int32_t getFirstFailAt() const; + bool firstFailAtIsSet() const; + void unsetFirstFailAt(); + void setFirstFailAt(int32_t value); + + /// + /// Last HTTP status from the summary URL, when known + /// + int32_t getLastStatus() const; + bool lastStatusIsSet() const; + void unsetLastStatus(); + void setLastStatus(int32_t value); + + /// + /// Epoch milliseconds of the next half-open probe for the summary URL, if any + /// + int32_t getNextProbeAt() const; + bool nextProbeAtIsSet() const; + void unsetNextProbeAt(); + void setNextProbeAt(int32_t value); + + /// + /// Currently configured URLs that are sticky auto-disabled (subset of `webhookUrl`). Does not include leftover URLs that are no longer configured. + /// + std::vector>> getDisabledWebhooks() const; + bool disabledWebhooksIsSet() const; + void unsetDisabledWebhooks(); + void setDisabledWebhooks(const std::vector>>& value); + + /// + /// One entry per currently configured URL. Prefer this over top-level `haveDisabledWebhooks` / `circuitState` when more than one webhook is set. + /// + std::vector> getWebhookStatuses() const; + bool webhookStatusesIsSet() const; + void unsetWebhookStatuses(); + void setWebhookStatuses(const std::vector>& value); /// @@ -79,8 +186,40 @@ class GetWebhook_200_response void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); protected: - utility::string_t m_WebhookUrl; - bool m_WebhookUrlIsSet; + boost::optional> m_WebhookUrl; + + bool m_HaveDisabledWebhooks; + bool m_HaveDisabledWebhooksIsSet; + + CircuitStateEnum m_CircuitState; + bool m_CircuitStateIsSet; + + utility::string_t m_Reason; + bool m_ReasonIsSet; + + int32_t m_Fails; + bool m_FailsIsSet; + + int32_t m_Trips; + bool m_TripsIsSet; + + int32_t m_DisabledAt; + bool m_DisabledAtIsSet; + + int32_t m_FirstFailAt; + bool m_FirstFailAtIsSet; + + int32_t m_LastStatus; + bool m_LastStatusIsSet; + + int32_t m_NextProbeAt; + bool m_NextProbeAtIsSet; + + std::vector>> m_DisabledWebhooks; + bool m_DisabledWebhooksIsSet; + + std::vector> m_WebhookStatuses; + bool m_WebhookStatusesIsSet; std::map m_AdditionalProperties; bool m_AdditionalPropertiesIsSet; diff --git a/include/one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h b/include/one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h new file mode 100644 index 0000000..bd4473c --- /dev/null +++ b/include/one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class GetWebhook_200_response_webhookUrl : public ModelBase { +public: + using VariantType = std::variant, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_array()) { std::vector value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h b/include/one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h index 62784f2..98da863 100644 --- a/include/one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h +++ b/include/one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/InitiateCallRequest.h b/include/one-msg-sdk/model/InitiateCallRequest.h index 7140439..4561c34 100644 --- a/include/one-msg-sdk/model/InitiateCallRequest.h +++ b/include/one-msg-sdk/model/InitiateCallRequest.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/InitiateCallRequest_session.h b/include/one-msg-sdk/model/InitiateCallRequest_session.h index 4540952..efbbd80 100644 --- a/include/one-msg-sdk/model/InitiateCallRequest_session.h +++ b/include/one-msg-sdk/model/InitiateCallRequest_session.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/InitiateCallResponse.h b/include/one-msg-sdk/model/InitiateCallResponse.h index aaa54aa..a003da2 100644 --- a/include/one-msg-sdk/model/InitiateCallResponse.h +++ b/include/one-msg-sdk/model/InitiateCallResponse.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/InitiateCallResponse_calls_inner.h b/include/one-msg-sdk/model/InitiateCallResponse_calls_inner.h index 6b3a532..252f196 100644 --- a/include/one-msg-sdk/model/InitiateCallResponse_calls_inner.h +++ b/include/one-msg-sdk/model/InitiateCallResponse_calls_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/InitiateCallResponse_response.h b/include/one-msg-sdk/model/InitiateCallResponse_response.h index 28963b4..8b0f23e 100644 --- a/include/one-msg-sdk/model/InitiateCallResponse_response.h +++ b/include/one-msg-sdk/model/InitiateCallResponse_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ListBlockedUsers_200_response.h b/include/one-msg-sdk/model/ListBlockedUsers_200_response.h index 62aed9d..06c85ad 100644 --- a/include/one-msg-sdk/model/ListBlockedUsers_200_response.h +++ b/include/one-msg-sdk/model/ListBlockedUsers_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ListFlows_200_response.h b/include/one-msg-sdk/model/ListFlows_200_response.h index aba1f3b..3fb121c 100644 --- a/include/one-msg-sdk/model/ListFlows_200_response.h +++ b/include/one-msg-sdk/model/ListFlows_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ListMessages_200_response.h b/include/one-msg-sdk/model/ListMessages_200_response.h index b3ec799..9e3e28e 100644 --- a/include/one-msg-sdk/model/ListMessages_200_response.h +++ b/include/one-msg-sdk/model/ListMessages_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/ListSettings_200_response.h b/include/one-msg-sdk/model/ListSettings_200_response.h new file mode 100644 index 0000000..d7b12d2 --- /dev/null +++ b/include/one-msg-sdk/model/ListSettings_200_response.h @@ -0,0 +1,291 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * ListSettings_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_ListSettings_200_response_H_ +#define ONEMSG_SDK_MODEL_ListSettings_200_response_H_ + +#include +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include "one-msg-sdk/model/WebhookUrlStatus.h" +#include +#include +#include +#include "one-msg-sdk/model/ListSettings_200_response_webhookUrl.h" +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class ListSettings_200_response + : public ModelBase +{ +public: + ListSettings_200_response(); + virtual ~ListSettings_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// ListSettings_200_response members + + enum class CircuitStateEnum + { + OK, + DEGRADED, + OPEN, + HALF_OPEN, + DISABLED, + }; + /// + /// Compatibility scalar for **one** URL (first sticky-disabled, else first configured). Prefer `webhookStatuses[].circuitState`. + /// + + CircuitStateEnum toCircuitStateEnum(const utility::string_t& value) const; + const utility::string_t fromCircuitStateEnum(const CircuitStateEnum value) const; + + + std::shared_ptr getWebhookUrl() const; + bool webhookUrlIsSet() const; + void unsetWebhookUrl(); + void setWebhookUrl(const std::shared_ptr& value); + + /// + /// Retry webhooks until acknowledged + /// + bool isGuaranteedHooks() const; + bool guaranteedHooksIsSet() const; + void unsetGuaranteedHooks(); + void setGuaranteedHooks(bool value); + + /// + /// Include message ACK / status events in webhooks + /// + bool isAckNotificationsOn() const; + bool ackNotificationsOnIsSet() const; + void unsetAckNotificationsOn(); + void setAckNotificationsOn(bool value); + + /// + /// Forward raw provider webhook payloads + /// + bool isRawHooks() const; + bool rawHooksIsSet() const; + void unsetRawHooks(); + void setRawHooks(bool value); + + bool isMmLiteEnabled() const; + bool mmLiteEnabledIsSet() const; + void unsetMm_lite_enabled(); + void setMmLiteEnabled(bool value); + + bool isTemplateAnalyticsEnabled() const; + bool templateAnalyticsEnabledIsSet() const; + void unsetTemplate_analytics_enabled(); + void setTemplateAnalyticsEnabled(bool value); + + bool isCtaUrlLinkTrackingOptedOut() const; + bool ctaUrlLinkTrackingOptedOutIsSet() const; + void unsetCta_url_link_tracking_opted_out(); + void setCtaUrlLinkTrackingOptedOut(bool value); + + /// + /// `true` when at least one URL in `webhookUrl` is sticky auto-disabled. Not \"the channel is dead\": other configured URLs still receive events. + /// + bool isHaveDisabledWebhooks() const; + bool haveDisabledWebhooksIsSet() const; + void unsetHaveDisabledWebhooks(); + void setHaveDisabledWebhooks(bool value); + + /// + /// Compatibility scalar for **one** URL (first sticky-disabled, else first configured). Prefer `webhookStatuses[].circuitState`. + /// + CircuitStateEnum getCircuitState() const; + bool circuitStateIsSet() const; + void unsetCircuitState(); + void setCircuitState(const CircuitStateEnum value); + + /// + /// Last qualifying fail reason of the summary URL + /// + utility::string_t getReason() const; + bool reasonIsSet() const; + void unsetReason(); + void setReason(const utility::string_t& value); + + /// + /// Diagnostic only (summary URL). Qualifying failures in the rolling ~10 minute breaker window — not lifetime. Prefer `webhookStatuses`. + /// + int32_t getFails() const; + bool failsIsSet() const; + void unsetFails(); + void setFails(int32_t value); + + /// + /// Diagnostic only (summary URL). Failed recovery probes (≈15 min → 1 h → 6 h). Sticky disable after 3. Not a blind unblock timer. + /// + int32_t getTrips() const; + bool tripsIsSet() const; + void unsetTrips(); + void setTrips(int32_t value); + + /// + /// Epoch milliseconds when the summary URL became sticky-disabled + /// + int32_t getDisabledAt() const; + bool disabledAtIsSet() const; + void unsetDisabledAt(); + void setDisabledAt(int32_t value); + + /// + /// Diagnostic only (summary URL). Epoch ms of the first fail in the current ~10 minute window (pairs with `fails`). + /// + int32_t getFirstFailAt() const; + bool firstFailAtIsSet() const; + void unsetFirstFailAt(); + void setFirstFailAt(int32_t value); + + /// + /// Last HTTP status from the summary URL, when known + /// + int32_t getLastStatus() const; + bool lastStatusIsSet() const; + void unsetLastStatus(); + void setLastStatus(int32_t value); + + /// + /// Epoch milliseconds of the next half-open probe for the summary URL, if any + /// + int32_t getNextProbeAt() const; + bool nextProbeAtIsSet() const; + void unsetNextProbeAt(); + void setNextProbeAt(int32_t value); + + /// + /// Currently configured URLs that are sticky auto-disabled (subset of `webhookUrl`) + /// + std::vector>> getDisabledWebhooks() const; + bool disabledWebhooksIsSet() const; + void unsetDisabledWebhooks(); + void setDisabledWebhooks(const std::vector>>& value); + + /// + /// One entry per currently configured URL. Prefer this over top-level `haveDisabledWebhooks` / `circuitState`. + /// + std::vector> getWebhookStatuses() const; + bool webhookStatusesIsSet() const; + void unsetWebhookStatuses(); + void setWebhookStatuses(const std::vector>& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + std::shared_ptr m_WebhookUrl; + bool m_WebhookUrlIsSet; + + bool m_GuaranteedHooks; + bool m_GuaranteedHooksIsSet; + + bool m_AckNotificationsOn; + bool m_AckNotificationsOnIsSet; + + bool m_RawHooks; + bool m_RawHooksIsSet; + + bool m_Mm_lite_enabled; + bool m_Mm_lite_enabledIsSet; + + bool m_Template_analytics_enabled; + bool m_Template_analytics_enabledIsSet; + + bool m_Cta_url_link_tracking_opted_out; + bool m_Cta_url_link_tracking_opted_outIsSet; + + bool m_HaveDisabledWebhooks; + bool m_HaveDisabledWebhooksIsSet; + + CircuitStateEnum m_CircuitState; + bool m_CircuitStateIsSet; + + utility::string_t m_Reason; + bool m_ReasonIsSet; + + int32_t m_Fails; + bool m_FailsIsSet; + + int32_t m_Trips; + bool m_TripsIsSet; + + int32_t m_DisabledAt; + bool m_DisabledAtIsSet; + + int32_t m_FirstFailAt; + bool m_FirstFailAtIsSet; + + int32_t m_LastStatus; + bool m_LastStatusIsSet; + + int32_t m_NextProbeAt; + bool m_NextProbeAtIsSet; + + std::vector>> m_DisabledWebhooks; + bool m_DisabledWebhooksIsSet; + + std::vector> m_WebhookStatuses; + bool m_WebhookStatusesIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_ListSettings_200_response_H_ */ diff --git a/include/one-msg-sdk/model/ListSettings_200_response_webhookUrl.h b/include/one-msg-sdk/model/ListSettings_200_response_webhookUrl.h new file mode 100644 index 0000000..3eaf8c5 --- /dev/null +++ b/include/one-msg-sdk/model/ListSettings_200_response_webhookUrl.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class ListSettings_200_response_webhookUrl : public ModelBase { +public: + using VariantType = std::variant, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_array()) { std::vector value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/ListTemplates_200_response.h b/include/one-msg-sdk/model/ListTemplates_200_response.h index d4f741d..c329742 100644 --- a/include/one-msg-sdk/model/ListTemplates_200_response.h +++ b/include/one-msg-sdk/model/ListTemplates_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/MessageSentResponse.h b/include/one-msg-sdk/model/MessageSentResponse.h index 6c75ac7..dd3fe87 100644 --- a/include/one-msg-sdk/model/MessageSentResponse.h +++ b/include/one-msg-sdk/model/MessageSentResponse.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h b/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h index 038d288..838c620 100644 --- a/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h +++ b/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h b/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h new file mode 100644 index 0000000..1146807 --- /dev/null +++ b/include/one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h @@ -0,0 +1,78 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * PatchFlowsFlowIdAssets_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_PatchFlowsFlowIdAssets_request_H_ +#define ONEMSG_SDK_MODEL_PatchFlowsFlowIdAssets_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class PatchFlowsFlowIdAssets_request + : public ModelBase +{ +public: + PatchFlowsFlowIdAssets_request(); + virtual ~PatchFlowsFlowIdAssets_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// PatchFlowsFlowIdAssets_request members + + + /// + /// WhatsApp Flow JSON document + /// + std::map> getFlowJson() const; + bool flowJsonIsSet() const; + void unsetFlowJson(); + void setFlowJson(const std::map>& value); + + +protected: + std::map> m_FlowJson; + bool m_FlowJsonIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_PatchFlowsFlowIdAssets_request_H_ */ diff --git a/include/one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h b/include/one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h new file mode 100644 index 0000000..c0cb0f2 --- /dev/null +++ b/include/one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h @@ -0,0 +1,111 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * PatchFlowsFlowIdMetadata_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_PatchFlowsFlowIdMetadata_request_H_ +#define ONEMSG_SDK_MODEL_PatchFlowsFlowIdMetadata_request_H_ + +#include +#include + +#include "one-msg-sdk/ModelBase.h" + +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class PatchFlowsFlowIdMetadata_request + : public ModelBase +{ +public: + PatchFlowsFlowIdMetadata_request(); + virtual ~PatchFlowsFlowIdMetadata_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// PatchFlowsFlowIdMetadata_request members + + enum class CategoriesEnum + { + SIGN_UP, + SIGN_IN, + APPOINTMENT_BOOKING, + LEAD_GENERATION, + CONTACT_US, + CUSTOMER_SUPPORT, + SURVEY, + OTHER, + }; + CategoriesEnum toCategoriesEnum(const utility::string_t& value) const; + const utility::string_t fromCategoriesEnum(const CategoriesEnum value) const; + std::vector toCategoriesEnum(const std::vector& value) const; + std::vector fromCategoriesEnum(const std::vector& value) const; + + + utility::string_t getName() const; + bool nameIsSet() const; + void unsetName(); + void setName(const utility::string_t& value); + + std::vector getCategories() const; + bool categoriesIsSet() const; + void unsetCategories(); + void setCategories(const std::vector value); + + /// + /// HTTPS endpoint for the Flow data channel + /// + utility::string_t getEndpointUri() const; + bool endpointUriIsSet() const; + void unsetEndpointUri(); + void setEndpointUri(const utility::string_t& value); + + +protected: + utility::string_t m_Name; + bool m_NameIsSet; + + std::vector m_Categories; + bool m_CategoriesIsSet; + + utility::string_t m_EndpointUri; + bool m_EndpointUriIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_PatchFlowsFlowIdMetadata_request_H_ */ diff --git a/include/one-msg-sdk/model/ProfileInfo.h b/include/one-msg-sdk/model/ProfileInfo.h index e76e939..f4abb35 100644 --- a/include/one-msg-sdk/model/ProfileInfo.h +++ b/include/one-msg-sdk/model/ProfileInfo.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/RemoveTemplate_request.h b/include/one-msg-sdk/model/RemoveTemplate_request.h new file mode 100644 index 0000000..069c1b3 --- /dev/null +++ b/include/one-msg-sdk/model/RemoveTemplate_request.h @@ -0,0 +1,77 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * RemoveTemplate_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_RemoveTemplate_request_H_ +#define ONEMSG_SDK_MODEL_RemoveTemplate_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class RemoveTemplate_request + : public ModelBase +{ +public: + RemoveTemplate_request(); + virtual ~RemoveTemplate_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// RemoveTemplate_request members + + + /// + /// Template name to delete + /// + utility::string_t getName() const; + bool nameIsSet() const; + void unsetName(); + void setName(const utility::string_t& value); + + +protected: + utility::string_t m_Name; + bool m_NameIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_RemoveTemplate_request_H_ */ diff --git a/include/one-msg-sdk/model/RetrieveMedia_200_response.h b/include/one-msg-sdk/model/RetrieveMedia_200_response.h index 94b5fb5..7b82e60 100644 --- a/include/one-msg-sdk/model/RetrieveMedia_200_response.h +++ b/include/one-msg-sdk/model/RetrieveMedia_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendAddressMessage_request.h b/include/one-msg-sdk/model/SendAddressMessage_request.h index 06a9693..cc1816d 100644 --- a/include/one-msg-sdk/model/SendAddressMessage_request.h +++ b/include/one-msg-sdk/model/SendAddressMessage_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendButton_request.h b/include/one-msg-sdk/model/SendButton_request.h index 50b9c33..789146c 100644 --- a/include/one-msg-sdk/model/SendButton_request.h +++ b/include/one-msg-sdk/model/SendButton_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -23,8 +23,11 @@ #include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" #include "one-msg-sdk/model/SendButton_request_sections_inner.h" +#include "one-msg-sdk/AnyType.h" #include +#include #include namespace onemsg { @@ -57,11 +60,30 @@ class SendButton_request /// SendButton_request members + /// + /// Recipient phone with country code. Use phone or chatId. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + /// + /// Optional Cloud API wamid to quote + /// + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + utility::string_t getBody() const; bool bodyIsSet() const; void unsetBody(); @@ -72,6 +94,22 @@ class SendButton_request void unsetFooter(); void setFooter(const utility::string_t& value); + /// + /// Optional interactive header (text/image/video/document) + /// + std::map> getHeader() const; + bool headerIsSet() const; + void unsetHeader(); + void setHeader(const std::map>& value); + + /// + /// Legacy alias for sections (`[{id,title}]`) + /// + std::vector> getButtons() const; + bool buttonsIsSet() const; + void unsetButtons(); + void setButtons(const std::vector>& value); + std::vector> getSections() const; bool sectionsIsSet() const; void unsetSections(); @@ -82,12 +120,24 @@ class SendButton_request utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + utility::string_t m_Body; bool m_BodyIsSet; utility::string_t m_Footer; bool m_FooterIsSet; + std::map> m_Header; + bool m_HeaderIsSet; + + std::vector> m_Buttons; + bool m_ButtonsIsSet; + std::vector> m_Sections; bool m_SectionsIsSet; diff --git a/include/one-msg-sdk/model/SendButton_request_sections_inner.h b/include/one-msg-sdk/model/SendButton_request_sections_inner.h index fd2fc71..40598a5 100644 --- a/include/one-msg-sdk/model/SendButton_request_sections_inner.h +++ b/include/one-msg-sdk/model/SendButton_request_sections_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendButton_request_sections_inner_reply.h b/include/one-msg-sdk/model/SendButton_request_sections_inner_reply.h index 6d8b115..bb234f5 100644 --- a/include/one-msg-sdk/model/SendButton_request_sections_inner_reply.h +++ b/include/one-msg-sdk/model/SendButton_request_sections_inner_reply.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendCarousel_request_1.h b/include/one-msg-sdk/model/SendCarousel_request_1.h index 4c4eac7..5909373 100644 --- a/include/one-msg-sdk/model/SendCarousel_request_1.h +++ b/include/one-msg-sdk/model/SendCarousel_request_1.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -24,7 +24,9 @@ #include "one-msg-sdk/ModelBase.h" #include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" #include +#include #include namespace onemsg { @@ -56,11 +58,25 @@ class SendCarousel_request_1 /// SendCarousel_request_1 members + /// + /// Text shown above the carousel + /// utility::string_t getBody() const; bool bodyIsSet() const; void unsetBody(); void setBody(const utility::string_t& value); + /// + /// Preferred. 2–10 carousel cards. + /// + std::vector>> getCards() const; + bool cardsIsSet() const; + void unsetCards(); + void setCards(const std::vector>>& value); + + /// + /// Template-like alternative — include a CAROUSEL component with cards + /// std::vector> getParams() const; bool paramsIsSet() const; void unsetParams(); @@ -86,6 +102,9 @@ class SendCarousel_request_1 utility::string_t m_Body; bool m_BodyIsSet; + std::vector>> m_Cards; + bool m_CardsIsSet; + std::vector> m_Params; bool m_ParamsIsSet; diff --git a/include/one-msg-sdk/model/SendContact_request.h b/include/one-msg-sdk/model/SendContact_request.h index 1dd5a72..764de60 100644 --- a/include/one-msg-sdk/model/SendContact_request.h +++ b/include/one-msg-sdk/model/SendContact_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -25,12 +25,14 @@ #include "one-msg-sdk/model/SendContact_request_contacts_inner.h" #include +#include "one-msg-sdk/model/SendContact_request_contact.h" #include namespace onemsg { namespace sdk { namespace model { +class SendContact_request_contact; class SendContact_request_contacts_inner; @@ -57,11 +59,32 @@ class SendContact_request /// SendContact_request members + /// + /// Recipient phone with country code. Use phone or chatId. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + + std::shared_ptr getContact() const; + bool contactIsSet() const; + void unsetContact(); + void setContact(const std::shared_ptr& value); + std::vector> getContacts() const; bool contactsIsSet() const; void unsetContacts(); @@ -72,6 +95,15 @@ class SendContact_request utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + + std::shared_ptr m_Contact; + bool m_ContactIsSet; + std::vector> m_Contacts; bool m_ContactsIsSet; diff --git a/include/one-msg-sdk/model/SendContact_request_contact.h b/include/one-msg-sdk/model/SendContact_request_contact.h new file mode 100644 index 0000000..5f6de01 --- /dev/null +++ b/include/one-msg-sdk/model/SendContact_request_contact.h @@ -0,0 +1,115 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * SendContact_request_contact.h + * + * Simple contact card. Use this or `contacts`. + */ + +#ifndef ONEMSG_SDK_MODEL_SendContact_request_contact_H_ +#define ONEMSG_SDK_MODEL_SendContact_request_contact_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include "one-msg-sdk/model/SendContact_request_contact_name.h" +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +/// +/// Simple contact card. Use this or `contacts`. +/// +class SendContact_request_contact + : public ModelBase +{ +public: + SendContact_request_contact(); + virtual ~SendContact_request_contact(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// SendContact_request_contact members + + + std::shared_ptr getName() const; + bool nameIsSet() const; + void unsetName(); + void setName(const std::shared_ptr& value); + + /// + /// Contact phone in E.164 (`+79181976551`), not a timestamp + /// + utility::string_t getPhone() const; + bool phoneIsSet() const; + void unsetPhone(); + void setPhone(const utility::string_t& value); + + utility::string_t getEmail() const; + bool emailIsSet() const; + void unsetEmail(); + void setEmail(const utility::string_t& value); + + std::map> getOrg() const; + bool orgIsSet() const; + void unsetOrg(); + void setOrg(const std::map>& value); + + utility::string_t getUrl() const; + bool urlIsSet() const; + void unsetUrl(); + void setUrl(const utility::string_t& value); + + +protected: + std::shared_ptr m_Name; + bool m_NameIsSet; + + utility::string_t m_Phone; + bool m_PhoneIsSet; + + utility::string_t m_Email; + bool m_EmailIsSet; + + std::map> m_Org; + bool m_OrgIsSet; + + utility::string_t m_Url; + bool m_UrlIsSet; + +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_SendContact_request_contact_H_ */ diff --git a/include/one-msg-sdk/model/SendContact_request_contact_name.h b/include/one-msg-sdk/model/SendContact_request_contact_name.h new file mode 100644 index 0000000..a81b0f9 --- /dev/null +++ b/include/one-msg-sdk/model/SendContact_request_contact_name.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class SendContact_request_contact_name : public ModelBase { +public: + using VariantType = std::variant>, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_object()) { std::map> value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/SendContact_request_contacts_inner.h b/include/one-msg-sdk/model/SendContact_request_contacts_inner.h index c336a0d..e7208b5 100644 --- a/include/one-msg-sdk/model/SendContact_request_contacts_inner.h +++ b/include/one-msg-sdk/model/SendContact_request_contacts_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -27,6 +27,7 @@ #include "one-msg-sdk/model/SendContact_request_contacts_inner_name.h" #include "one-msg-sdk/AnyType.h" #include +#include #include #include "one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h" @@ -72,15 +73,15 @@ class SendContact_request_contacts_inner void unsetBirthday(); void setBirthday(const utility::string_t& value); - std::vector> getAddresses() const; + std::vector>> getAddresses() const; bool addressesIsSet() const; void unsetAddresses(); - void setAddresses(const std::vector>& value); + void setAddresses(const std::vector>>& value); - std::vector> getEmails() const; + std::vector>> getEmails() const; bool emailsIsSet() const; void unsetEmails(); - void setEmails(const std::vector>& value); + void setEmails(const std::vector>>& value); std::shared_ptr getOrg() const; bool orgIsSet() const; @@ -92,10 +93,10 @@ class SendContact_request_contacts_inner void unsetPhones(); void setPhones(const std::vector>& value); - std::vector> getUrls() const; + std::vector>> getUrls() const; bool urlsIsSet() const; void unsetUrls(); - void setUrls(const std::vector>& value); + void setUrls(const std::vector>>& value); protected: @@ -105,10 +106,10 @@ class SendContact_request_contacts_inner utility::string_t m_Birthday; bool m_BirthdayIsSet; - std::vector> m_Addresses; + std::vector>> m_Addresses; bool m_AddressesIsSet; - std::vector> m_Emails; + std::vector>> m_Emails; bool m_EmailsIsSet; std::shared_ptr m_Org; @@ -117,7 +118,7 @@ class SendContact_request_contacts_inner std::vector> m_Phones; bool m_PhonesIsSet; - std::vector> m_Urls; + std::vector>> m_Urls; bool m_UrlsIsSet; }; diff --git a/include/one-msg-sdk/model/SendContact_request_contacts_inner_name.h b/include/one-msg-sdk/model/SendContact_request_contacts_inner_name.h index d8d9751..7b3470d 100644 --- a/include/one-msg-sdk/model/SendContact_request_contacts_inner_name.h +++ b/include/one-msg-sdk/model/SendContact_request_contacts_inner_name.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendContact_request_contacts_inner_org.h b/include/one-msg-sdk/model/SendContact_request_contacts_inner_org.h index d86390e..92e8a2f 100644 --- a/include/one-msg-sdk/model/SendContact_request_contacts_inner_org.h +++ b/include/one-msg-sdk/model/SendContact_request_contacts_inner_org.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h b/include/one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h index 829ee66..2d2eb16 100644 --- a/include/one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h +++ b/include/one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -54,6 +54,9 @@ class SendContact_request_contacts_inner_phones_inner /// SendContact_request_contacts_inner_phones_inner members + /// + /// E.164 phone (`+79181976551`). Not a timestamp. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); diff --git a/include/one-msg-sdk/model/SendCtaUrl_request.h b/include/one-msg-sdk/model/SendCtaUrl_request.h index 80b59cf..5678ad6 100644 --- a/include/one-msg-sdk/model/SendCtaUrl_request.h +++ b/include/one-msg-sdk/model/SendCtaUrl_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendFileRequest.h b/include/one-msg-sdk/model/SendFileRequest.h index 8e1316a..98b7bd5 100644 --- a/include/one-msg-sdk/model/SendFileRequest.h +++ b/include/one-msg-sdk/model/SendFileRequest.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendFlow_request_1.h b/include/one-msg-sdk/model/SendFlow_request_1.h index 50a705f..3718074 100644 --- a/include/one-msg-sdk/model/SendFlow_request_1.h +++ b/include/one-msg-sdk/model/SendFlow_request_1.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendFlow_request_1_header.h b/include/one-msg-sdk/model/SendFlow_request_1_header.h index 3d4c95b..376a2a0 100644 --- a/include/one-msg-sdk/model/SendFlow_request_1_header.h +++ b/include/one-msg-sdk/model/SendFlow_request_1_header.h @@ -1,90 +1,63 @@ -/** - * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ - * - * The version of the OpenAPI document: 1.0.0 - * Contact: support@1msg.io - * - * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -/* - * SendFlow_request_1_header.h - * - * - */ - -#ifndef ONEMSG_SDK_MODEL_SendFlow_request_1_header_H_ -#define ONEMSG_SDK_MODEL_SendFlow_request_1_header_H_ - -#include -#include - +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once #include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include +namespace onemsg { namespace sdk { namespace model { -namespace onemsg { -namespace sdk { -namespace model { - - - -class SendFlow_request_1_header -{ +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class SendFlow_request_1_header : public ModelBase { public: - SendFlow_request_1_header() = default; - ~SendFlow_request_1_header() = default; - - ///////////////////////////////////////////// - - void validate(); - - web::json::value toJson() const; + using VariantType = std::variant, utility::string_t>; - template - bool fromJson(const web::json::value& json) { - // convert json to Target type + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + if (std::holds_alternative>(m_variantValue) && !std::get>(m_variantValue)) throw std::invalid_argument("Flow header cannot be null"); + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_object()) { std::shared_ptr value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { Target target; - if (!target.fromJson(json)) { - return false; - } - - m_variantValue = target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); return true; } - - void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const; - - template - bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) { - // convert multipart to Target type + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; Target target; - if (!target.fromMultiPart(multipart, namePrefix)) { - return false; - } - - m_variantValue = target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); return true; } - - ///////////////////////////////////////////// - /// SendFlow_request_1_header members - - using VariantType = std::variant, utility::string_t>; - - const VariantType& getVariant() const; - void setVariant(VariantType value); - protected: VariantType m_variantValue; }; - - -} -} -} - -#endif /* ONEMSG_SDK_MODEL_SendFlow_request_1_header_H_ */ +} } } diff --git a/include/one-msg-sdk/model/SendFlow_request_header.h b/include/one-msg-sdk/model/SendFlow_request_header.h index 56628ce..582497a 100644 --- a/include/one-msg-sdk/model/SendFlow_request_header.h +++ b/include/one-msg-sdk/model/SendFlow_request_header.h @@ -1,90 +1,63 @@ -/** - * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ - * - * The version of the OpenAPI document: 1.0.0 - * Contact: support@1msg.io - * - * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -/* - * SendFlow_request_header.h - * - * Flow header (string or text header object) - */ - -#ifndef ONEMSG_SDK_MODEL_SendFlow_request_header_H_ -#define ONEMSG_SDK_MODEL_SendFlow_request_header_H_ - -#include -#include - +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once #include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include +namespace onemsg { namespace sdk { namespace model { -namespace onemsg { -namespace sdk { -namespace model { - - - -class SendFlow_request_header -{ +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class SendFlow_request_header : public ModelBase { public: - SendFlow_request_header() = default; - ~SendFlow_request_header() = default; - - ///////////////////////////////////////////// - - void validate(); - - web::json::value toJson() const; + using VariantType = std::variant, utility::string_t>; - template - bool fromJson(const web::json::value& json) { - // convert json to Target type + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + if (std::holds_alternative>(m_variantValue) && !std::get>(m_variantValue)) throw std::invalid_argument("Flow header cannot be null"); + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_object()) { std::shared_ptr value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { Target target; - if (!target.fromJson(json)) { - return false; - } - - m_variantValue = target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); return true; } - - void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const; - - template - bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) { - // convert multipart to Target type + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; Target target; - if (!target.fromMultiPart(multipart, namePrefix)) { - return false; - } - - m_variantValue = target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); return true; } - - ///////////////////////////////////////////// - /// SendFlow_request_header members - - using VariantType = std::variant, utility::string_t>; - - const VariantType& getVariant() const; - void setVariant(VariantType value); - protected: VariantType m_variantValue; }; - - -} -} -} - -#endif /* ONEMSG_SDK_MODEL_SendFlow_request_header_H_ */ +} } } diff --git a/include/one-msg-sdk/model/SendList_request.h b/include/one-msg-sdk/model/SendList_request.h index bc61d0a..1db32ff 100644 --- a/include/one-msg-sdk/model/SendList_request.h +++ b/include/one-msg-sdk/model/SendList_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -57,11 +57,27 @@ class SendList_request /// SendList_request members + /// + /// Recipient phone with country code. Use phone or chatId. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + utility::string_t getBody() const; bool bodyIsSet() const; void unsetBody(); @@ -87,6 +103,12 @@ class SendList_request utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + utility::string_t m_Body; bool m_BodyIsSet; diff --git a/include/one-msg-sdk/model/SendList_request_sections_inner.h b/include/one-msg-sdk/model/SendList_request_sections_inner.h index cb04e96..f5b0950 100644 --- a/include/one-msg-sdk/model/SendList_request_sections_inner.h +++ b/include/one-msg-sdk/model/SendList_request_sections_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendList_request_sections_inner_rows_inner.h b/include/one-msg-sdk/model/SendList_request_sections_inner_rows_inner.h index 5961837..5b52222 100644 --- a/include/one-msg-sdk/model/SendList_request_sections_inner_rows_inner.h +++ b/include/one-msg-sdk/model/SendList_request_sections_inner_rows_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendLocationRequest_request.h b/include/one-msg-sdk/model/SendLocationRequest_request.h index 814352b..ef77772 100644 --- a/include/one-msg-sdk/model/SendLocationRequest_request.h +++ b/include/one-msg-sdk/model/SendLocationRequest_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -54,11 +54,27 @@ class SendLocationRequest_request /// SendLocationRequest_request members + /// + /// Recipient phone with country code. Use phone or chatId. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + utility::string_t getBody() const; bool bodyIsSet() const; void unsetBody(); @@ -69,6 +85,12 @@ class SendLocationRequest_request utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + utility::string_t m_Body; bool m_BodyIsSet; diff --git a/include/one-msg-sdk/model/SendLocation_request_1.h b/include/one-msg-sdk/model/SendLocation_request_1.h index 34b0f41..f933b14 100644 --- a/include/one-msg-sdk/model/SendLocation_request_1.h +++ b/include/one-msg-sdk/model/SendLocation_request_1.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendMessageRequest.h b/include/one-msg-sdk/model/SendMessageRequest.h index 5042a19..418d5e4 100644 --- a/include/one-msg-sdk/model/SendMessageRequest.h +++ b/include/one-msg-sdk/model/SendMessageRequest.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -74,7 +74,7 @@ class SendMessageRequest void setQuotedMsgId(const utility::string_t& value); /// - /// Chat ID in format: phone@c.us (individual) or phone@g.us (group) + /// Recipient chat ID: phone@c.us, group@g.us, or BSUID@lid /// utility::string_t getChatId() const; bool chatIdIsSet() const; diff --git a/include/one-msg-sdk/model/SendOrderDetails_request.h b/include/one-msg-sdk/model/SendOrderDetails_request.h index 0c01338..a5ea8c1 100644 --- a/include/one-msg-sdk/model/SendOrderDetails_request.h +++ b/include/one-msg-sdk/model/SendOrderDetails_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendOrderDetails_request_language.h b/include/one-msg-sdk/model/SendOrderDetails_request_language.h index 3d368c2..0b9d739 100644 --- a/include/one-msg-sdk/model/SendOrderDetails_request_language.h +++ b/include/one-msg-sdk/model/SendOrderDetails_request_language.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendOrderDetails_request_order.h b/include/one-msg-sdk/model/SendOrderDetails_request_order.h index 1b5d8e3..2c20a68 100644 --- a/include/one-msg-sdk/model/SendOrderDetails_request_order.h +++ b/include/one-msg-sdk/model/SendOrderDetails_request_order.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner.h b/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner.h index 8301abf..3a0d388 100644 --- a/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner.h +++ b/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner_amount.h b/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner_amount.h index c306813..0bae660 100644 --- a/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner_amount.h +++ b/include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner_amount.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendPaymentRequest_request.h b/include/one-msg-sdk/model/SendPaymentRequest_request.h index 6c88d48..71a4e9d 100644 --- a/include/one-msg-sdk/model/SendPaymentRequest_request.h +++ b/include/one-msg-sdk/model/SendPaymentRequest_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendProduct_request.h b/include/one-msg-sdk/model/SendProduct_request.h new file mode 100644 index 0000000..49ff015 --- /dev/null +++ b/include/one-msg-sdk/model/SendProduct_request.h @@ -0,0 +1,157 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * SendProduct_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_SendProduct_request_H_ +#define ONEMSG_SDK_MODEL_SendProduct_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class SendProduct_request + : public ModelBase +{ +public: + SendProduct_request(); + virtual ~SendProduct_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// SendProduct_request members + + + /// + /// Recipient phone with country code. Use phone or chatId. + /// + utility::string_t getPhone() const; + bool phoneIsSet() const; + void unsetPhone(); + void setPhone(const utility::string_t& value); + + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + + /// + /// Optional message text shown with the product + /// + utility::string_t getBody() const; + bool bodyIsSet() const; + void unsetBody(); + void setBody(const utility::string_t& value); + + utility::string_t getFooter() const; + bool footerIsSet() const; + void unsetFooter(); + void setFooter(const utility::string_t& value); + + /// + /// Text header (product list only) + /// + utility::string_t getHeader() const; + bool headerIsSet() const; + void unsetHeader(); + void setHeader(const utility::string_t& value); + + /// + /// Catalog action (`catalog_id` + `product_retailer_id`, or `sections` for a list) + /// + std::map> getAction() const; + bool actionIsSet() const; + void unsetAction(); + void setAction(const std::map>& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + utility::string_t m_Phone; + bool m_PhoneIsSet; + + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + + utility::string_t m_Body; + bool m_BodyIsSet; + + utility::string_t m_Footer; + bool m_FooterIsSet; + + utility::string_t m_Header; + bool m_HeaderIsSet; + + std::map> m_Action; + bool m_ActionIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_SendProduct_request_H_ */ diff --git a/include/one-msg-sdk/model/SendReaction_request.h b/include/one-msg-sdk/model/SendReaction_request.h index 1a48db3..f7526be 100644 --- a/include/one-msg-sdk/model/SendReaction_request.h +++ b/include/one-msg-sdk/model/SendReaction_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -54,11 +54,22 @@ class SendReaction_request /// SendReaction_request members + /// + /// Recipient phone with country code. Use phone or chatId. + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + utility::string_t getBody() const; bool bodyIsSet() const; void unsetBody(); @@ -74,6 +85,9 @@ class SendReaction_request utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + utility::string_t m_Body; bool m_BodyIsSet; diff --git a/include/one-msg-sdk/model/SendSticker_request.h b/include/one-msg-sdk/model/SendSticker_request.h index e17329c..c0ca3c5 100644 --- a/include/one-msg-sdk/model/SendSticker_request.h +++ b/include/one-msg-sdk/model/SendSticker_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SendTemplate_request.h b/include/one-msg-sdk/model/SendTemplate_request.h index b846177..dbf7efe 100644 --- a/include/one-msg-sdk/model/SendTemplate_request.h +++ b/include/one-msg-sdk/model/SendTemplate_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -26,6 +26,7 @@ #include "one-msg-sdk/AnyType.h" #include #include "one-msg-sdk/model/SendTemplate_request_language.h" +#include #include namespace onemsg { @@ -58,6 +59,9 @@ class SendTemplate_request /// SendTemplate_request members + /// + /// Approved template name (template `name`, not the old HSM `element_name`) + /// utility::string_t getRTemplate() const; bool rTemplateIsSet() const; void unsetr_template(); @@ -68,21 +72,46 @@ class SendTemplate_request void unsetLanguage(); void setLanguage(const std::shared_ptr& value); + /// + /// Template namespace from `list_templates` + /// utility::string_t getRNamespace() const; bool rNamespaceIsSet() const; void unsetr_namespace(); void setRNamespace(const utility::string_t& value); - std::vector> getParams() const; + /// + /// Template components in WhatsApp Cloud API format. Each item is an object with `type` (`body`, `header`, `button`) and `parameters` (objects with `type` + `text` / media / action). Never a list of strings. Never HSM `localizable_params`. + /// + std::vector>> getParams() const; bool paramsIsSet() const; void unsetParams(); - void setParams(const std::vector>& value); + void setParams(const std::vector>>& value); + /// + /// Recipient phone with country code (use phone or chatId) + /// utility::string_t getPhone() const; bool phoneIsSet() const; void unsetPhone(); void setPhone(const utility::string_t& value); + /// + /// Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). Use phone or chatId. + /// + utility::string_t getChatId() const; + bool chatIdIsSet() const; + void unsetChatId(); + void setChatId(const utility::string_t& value); + + /// + /// Optional Cloud API wamid to quote + /// + utility::string_t getQuotedMsgId() const; + bool quotedMsgIdIsSet() const; + void unsetQuotedMsgId(); + void setQuotedMsgId(const utility::string_t& value); + /// /// Force Marketing Messages API (POST marketing_messages). If omitted: auto for MARKETING category when channel has mm_lite_enabled and mm_lite_available service settings. /// @@ -118,12 +147,18 @@ class SendTemplate_request utility::string_t m_r_namespace; bool m_r_namespaceIsSet; - std::vector> m_Params; + std::vector>> m_Params; bool m_ParamsIsSet; utility::string_t m_Phone; bool m_PhoneIsSet; + utility::string_t m_ChatId; + bool m_ChatIdIsSet; + + utility::string_t m_QuotedMsgId; + bool m_QuotedMsgIdIsSet; + bool m_UseMMlite; bool m_UseMMliteIsSet; diff --git a/include/one-msg-sdk/model/SendTemplate_request_language.h b/include/one-msg-sdk/model/SendTemplate_request_language.h index 755e617..26291cd 100644 --- a/include/one-msg-sdk/model/SendTemplate_request_language.h +++ b/include/one-msg-sdk/model/SendTemplate_request_language.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -13,7 +13,7 @@ /* * SendTemplate_request_language.h * - * + * Template language. Always set `policy` to `deterministic`. */ #ifndef ONEMSG_SDK_MODEL_SendTemplate_request_language_H_ @@ -31,6 +31,9 @@ namespace model { +/// +/// Template language. Always set `policy` to `deterministic`. +/// class SendTemplate_request_language : public ModelBase { @@ -54,6 +57,9 @@ class SendTemplate_request_language /// SendTemplate_request_language members + /// + /// Must be `deterministic` + /// utility::string_t getPolicy() const; bool policyIsSet() const; void unsetPolicy(); diff --git a/include/one-msg-sdk/model/SetWebhook_200_response.h b/include/one-msg-sdk/model/SetWebhook_200_response.h new file mode 100644 index 0000000..28a0182 --- /dev/null +++ b/include/one-msg-sdk/model/SetWebhook_200_response.h @@ -0,0 +1,105 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * SetWebhook_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_SetWebhook_200_response_H_ +#define ONEMSG_SDK_MODEL_SetWebhook_200_response_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class SetWebhook_200_response + : public ModelBase +{ +public: + SetWebhook_200_response(); + virtual ~SetWebhook_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// SetWebhook_200_response members + + + /// + /// True when the stored webhook URL(s) match the request + /// + bool isSet() const; + bool setIsSet() const; + void unsetset(); + void setSet(bool value); + + std::shared_ptr getWebhookUrl() const; + bool webhookUrlIsSet() const; + void unsetWebhookUrl(); + void setWebhookUrl(const std::shared_ptr& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + bool m_set; + bool m_setIsSet; + + std::shared_ptr m_WebhookUrl; + bool m_WebhookUrlIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_SetWebhook_200_response_H_ */ diff --git a/include/one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h b/include/one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h new file mode 100644 index 0000000..ce56563 --- /dev/null +++ b/include/one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class SetWebhook_200_response_webhookUrl : public ModelBase { +public: + using VariantType = std::variant, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_array()) { std::vector value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/SetWebhook_request.h b/include/one-msg-sdk/model/SetWebhook_request.h new file mode 100644 index 0000000..502d08b --- /dev/null +++ b/include/one-msg-sdk/model/SetWebhook_request.h @@ -0,0 +1,94 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * SetWebhook_request.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_SetWebhook_request_H_ +#define ONEMSG_SDK_MODEL_SetWebhook_request_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include "one-msg-sdk/model/SetWebhook_request_webhookUrl.h" + +namespace onemsg { +namespace sdk { +namespace model { + + + +class SetWebhook_request + : public ModelBase +{ +public: + SetWebhook_request(); + virtual ~SetWebhook_request(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// SetWebhook_request members + + + std::shared_ptr getWebhookUrl() const; + bool webhookUrlIsSet() const; + void unsetWebhookUrl(); + void setWebhookUrl(const std::shared_ptr& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + std::shared_ptr m_WebhookUrl; + bool m_WebhookUrlIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_SetWebhook_request_H_ */ diff --git a/include/one-msg-sdk/model/SetWebhook_request_webhookUrl.h b/include/one-msg-sdk/model/SetWebhook_request_webhookUrl.h new file mode 100644 index 0000000..c8e139b --- /dev/null +++ b/include/one-msg-sdk/model/SetWebhook_request_webhookUrl.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class SetWebhook_request_webhookUrl : public ModelBase { +public: + using VariantType = std::variant, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { + // Every stored alternative is a value; JSON null is rejected by fromJson. + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.is_array()) { std::vector value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/include/one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h b/include/one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h index 74a52e3..762c4cc 100644 --- a/include/one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h +++ b/include/one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/SuccessResponse.h b/include/one-msg-sdk/model/SuccessResponse.h index ce86ee3..7725d77 100644 --- a/include/one-msg-sdk/model/SuccessResponse.h +++ b/include/one-msg-sdk/model/SuccessResponse.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/UpdateCallingSettings_200_response.h b/include/one-msg-sdk/model/UpdateCallingSettings_200_response.h index f5aeb50..f8d2558 100644 --- a/include/one-msg-sdk/model/UpdateCallingSettings_200_response.h +++ b/include/one-msg-sdk/model/UpdateCallingSettings_200_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/UpdateCallingSettings_200_response_response.h b/include/one-msg-sdk/model/UpdateCallingSettings_200_response_response.h index 69584f6..920a385 100644 --- a/include/one-msg-sdk/model/UpdateCallingSettings_200_response_response.h +++ b/include/one-msg-sdk/model/UpdateCallingSettings_200_response_response.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/include/one-msg-sdk/model/UpdateMe_200_response.h b/include/one-msg-sdk/model/UpdateMe_200_response.h new file mode 100644 index 0000000..5004871 --- /dev/null +++ b/include/one-msg-sdk/model/UpdateMe_200_response.h @@ -0,0 +1,94 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * UpdateMe_200_response.h + * + * + */ + +#ifndef ONEMSG_SDK_MODEL_UpdateMe_200_response_H_ +#define ONEMSG_SDK_MODEL_UpdateMe_200_response_H_ + +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +class UpdateMe_200_response + : public ModelBase +{ +public: + UpdateMe_200_response(); + virtual ~UpdateMe_200_response(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// UpdateMe_200_response members + + + utility::string_t getResult() const; + bool resultIsSet() const; + void unsetResult(); + void setResult(const utility::string_t& value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + utility::string_t m_Result; + bool m_ResultIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_UpdateMe_200_response_H_ */ diff --git a/include/one-msg-sdk/model/UpdateMe_request.h b/include/one-msg-sdk/model/UpdateMe_request.h index 5dae293..bbe059d 100644 --- a/include/one-msg-sdk/model/UpdateMe_request.h +++ b/include/one-msg-sdk/model/UpdateMe_request.h @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -59,13 +59,16 @@ class UpdateMe_request /// - /// Profile About section + /// Profile About section (WhatsApp status text) /// utility::string_t getAbout() const; bool aboutIsSet() const; void unsetAbout(); void setAbout(const utility::string_t& value); + /// + /// Business address shown on the profile + /// utility::string_t getAddress() const; bool addressIsSet() const; void unsetAddress(); @@ -79,6 +82,9 @@ class UpdateMe_request void unsetDescription(); void setDescription(const utility::string_t& value); + /// + /// Business email shown on the profile + /// utility::string_t getEmail() const; bool emailIsSet() const; void unsetEmail(); @@ -100,6 +106,9 @@ class UpdateMe_request void unsetPhoto(); void setPhoto(const utility::string_t& value); + /// + /// Business website URLs + /// std::vector getWebsites() const; bool websitesIsSet() const; void unsetWebsites(); diff --git a/include/one-msg-sdk/model/WebhookUrlStatus.h b/include/one-msg-sdk/model/WebhookUrlStatus.h new file mode 100644 index 0000000..b72134d --- /dev/null +++ b/include/one-msg-sdk/model/WebhookUrlStatus.h @@ -0,0 +1,204 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * WebhookUrlStatus.h + * + * Circuit / auto-disable status for one configured webhook URL. The breaker is per URL (`instanceId` + URL hash), not per channel. + */ + +#ifndef ONEMSG_SDK_MODEL_WebhookUrlStatus_H_ +#define ONEMSG_SDK_MODEL_WebhookUrlStatus_H_ + +#include +#include + +#include "one-msg-sdk/ModelBase.h" + +#include "one-msg-sdk/AnyType.h" +#include +#include +#include + +namespace onemsg { +namespace sdk { +namespace model { + + + +/// +/// Circuit / auto-disable status for one configured webhook URL. The breaker is per URL (`instanceId` + URL hash), not per channel. +/// +class WebhookUrlStatus + : public ModelBase +{ +public: + WebhookUrlStatus(); + virtual ~WebhookUrlStatus(); + + ///////////////////////////////////////////// + /// ModelBase overrides + + void validate() override; + + web::json::value toJson() const override; + bool fromJson(const web::json::value& json) override; + + void toMultipart(std::shared_ptr multipart, const utility::string_t& namePrefix) const override; + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix) override; + + + ///////////////////////////////////////////// + /// WebhookUrlStatus members + + enum class CircuitStateEnum + { + OK, + DEGRADED, + OPEN, + HALF_OPEN, + DISABLED, + }; + /// + /// Delivery state for this URL only. `ok` delivering; `degraded` recent qualifying fails (still delivering, warning email on the 2nd fail); `open` skipping most deliveries pending a probe; `half_open` probe in flight (resume only on HTTP 2xx); `disabled` sticky auto-disabled until self-serve re-enable (`POST /webhook` / `POST /settings` with this URL) or a successful probe before sticky disable. + /// + + CircuitStateEnum toCircuitStateEnum(const utility::string_t& value) const; + const utility::string_t fromCircuitStateEnum(const CircuitStateEnum value) const; + + + /// + /// This webhook URL (same string as in `webhookUrl`) + /// + utility::string_t getUrl() const; + bool urlIsSet() const; + void unsetUrl(); + void setUrl(const utility::string_t& value); + + /// + /// Delivery state for this URL only. `ok` delivering; `degraded` recent qualifying fails (still delivering, warning email on the 2nd fail); `open` skipping most deliveries pending a probe; `half_open` probe in flight (resume only on HTTP 2xx); `disabled` sticky auto-disabled until self-serve re-enable (`POST /webhook` / `POST /settings` with this URL) or a successful probe before sticky disable. + /// + CircuitStateEnum getCircuitState() const; + bool circuitStateIsSet() const; + void unsetCircuitState(); + void setCircuitState(const CircuitStateEnum value); + + /// + /// Last qualifying fail reason, e.g. `http_404` or `timeout_or_network` + /// + utility::string_t getReason() const; + bool reasonIsSet() const; + void unsetReason(); + void setReason(const utility::string_t& value); + + /// + /// Diagnostic only — safe for clients to ignore. Number of qualifying delivery failures in the rolling ~10 minute breaker window (not lifetime, not \"how many times the customer retried\"). Prefer `circuitState` / `disabledWebhooks`. + /// + int32_t getFails() const; + bool failsIsSet() const; + void unsetFails(); + void setFails(int32_t value); + + /// + /// Diagnostic only — safe for clients to ignore. How many recovery probes already failed for this URL. Probes run on a schedule (≈15 min → 1 h → 6 h); sticky disable after 3 failed probes. The 6 h step is the last probe, not a blind \"unblock in 6 hours\" timer. + /// + int32_t getTrips() const; + bool tripsIsSet() const; + void unsetTrips(); + void setTrips(int32_t value); + + /// + /// Epoch milliseconds when this URL became sticky-disabled + /// + int32_t getDisabledAt() const; + bool disabledAtIsSet() const; + void unsetDisabledAt(); + void setDisabledAt(int32_t value); + + /// + /// Diagnostic only. Epoch ms of the first fail in the current ~10 minute window (pairs with `fails`; not a customer-facing period). + /// + int32_t getFirstFailAt() const; + bool firstFailAtIsSet() const; + void unsetFirstFailAt(); + void setFirstFailAt(int32_t value); + + /// + /// Last HTTP status from this URL, when known + /// + int32_t getLastStatus() const; + bool lastStatusIsSet() const; + void unsetLastStatus(); + void setLastStatus(int32_t value); + + /// + /// Epoch milliseconds of the next half-open probe, if any + /// + int32_t getNextProbeAt() const; + bool nextProbeAtIsSet() const; + void unsetNextProbeAt(); + void setNextProbeAt(int32_t value); + + + /// + /// Get additional properties (properties not defined in the schema) + /// + std::map getAdditionalProperties() const; + bool additionalPropertiesIsSet() const; + void unsetAdditionalProperties(); + /// + /// Set additional properties + /// + void setAdditionalProperties(const std::map& value); + /// + /// Add a single additional property + /// + void addAdditionalProperty(const utility::string_t& key, const web::json::value& value); + +protected: + utility::string_t m_Url; + bool m_UrlIsSet; + + CircuitStateEnum m_CircuitState; + bool m_CircuitStateIsSet; + + utility::string_t m_Reason; + bool m_ReasonIsSet; + + int32_t m_Fails; + bool m_FailsIsSet; + + int32_t m_Trips; + bool m_TripsIsSet; + + int32_t m_DisabledAt; + bool m_DisabledAtIsSet; + + int32_t m_FirstFailAt; + bool m_FirstFailAtIsSet; + + int32_t m_LastStatus; + bool m_LastStatusIsSet; + + int32_t m_NextProbeAt; + bool m_NextProbeAtIsSet; + + std::map m_AdditionalProperties; + bool m_AdditionalPropertiesIsSet; +}; + + +} +} +} + +#endif /* ONEMSG_SDK_MODEL_WebhookUrlStatus_H_ */ diff --git a/knip.json b/knip.json new file mode 100644 index 0000000..97f2c38 --- /dev/null +++ b/knip.json @@ -0,0 +1,12 @@ +{ + "entry": [ + "quality/generator/generate.mjs!", + "quality/generator/verify-negative.mjs!", + "quality/postprocess.mjs!", + "eslint.config.mjs", + "quality.config.mjs" + ], + "project": ["quality/**/*.mjs!", "*.mjs"], + "ignoreBinaries": ["java"], + "ignore": ["tools/quality/**"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..38e58c7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,15 @@ +{ + "name": "1msg-sdk-cpp-quality", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "1msg-sdk-cpp-quality", + "version": "1.0.0", + "engines": { + "node": "24.x" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6d9b9b5 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "1msg-sdk-cpp-quality", + "version": "1.0.0", + "private": true, + "type": "module", + "engines": { + "node": "24.x" + }, + "packageManager": "npm@11.17.0", + "scripts": { + "format:check": "node tools/quality/node_modules/prettier/bin/prettier.cjs --check \"quality/**/*.mjs\" \"*.mjs\" package.json knip.json .github/workflows/quality.yml AGENTS.md", + "format": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write \"quality/**/*.mjs\" \"*.mjs\" package.json knip.json .github/workflows/quality.yml AGENTS.md", + "lint:static": "node tools/quality/node_modules/eslint/bin/eslint.js . --max-warnings=0", + "quality:guards": "node tools/quality/run.mjs guards", + "lint:unused:production": "node tools/quality/run.mjs unused-production", + "lint:unused:full": "node tools/quality/run.mjs unused-full", + "lint:duplicates": "node tools/quality/run.mjs duplicates", + "lint:duplicates:full": "node tools/quality/run.mjs duplicates-full", + "test:quality": "node --test tools/quality/test/*.test.mjs", + "hooks:install": "node tools/quality/node_modules/husky/bin.js" + }, + "lint-staged": { + "*.{mjs,json,md,yml}": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write" + } +} diff --git a/quality.config.mjs b/quality.config.mjs new file mode 100644 index 0000000..ed8ca14 --- /dev/null +++ b/quality.config.mjs @@ -0,0 +1,14 @@ +export default { + schemaVersion: 1, + profile: "D", + defaultBranch: "main", + sourceRoots: ["quality", "eslint.config.mjs", "quality.config.mjs"], + generated: [], + comments: { + full: ["quality/**/*.mjs"], + }, + duplicatePaths: ["quality"], + duplicateMaxPercentage: 0, + duplicateFullPaths: ["quality"], + baselineDir: "quality/baselines", +}; diff --git a/quality/CMakeLists.txt b/quality/CMakeLists.txt new file mode 100644 index 0000000..7fc0c6a --- /dev/null +++ b/quality/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.16) +project(one-msg-sdk-quality CXX) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +enable_testing() +add_subdirectory(.. sdk) +add_executable(contract-smoke tests/contract.cpp) +target_link_libraries(contract-smoke PRIVATE one-msg-sdk) +add_test(NAME contract-smoke COMMAND contract-smoke) diff --git a/quality/consumer/CMakeLists.txt b/quality/consumer/CMakeLists.txt new file mode 100644 index 0000000..0b4cc39 --- /dev/null +++ b/quality/consumer/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.16) +project(one-msg-sdk-installed-consumer CXX) +set(CMAKE_CXX_STANDARD 20) +find_package(one-msg-sdk REQUIRED) +enable_testing() +add_executable(installed-contract ../tests/contract.cpp) +target_link_libraries(installed-contract PRIVATE one-msg-sdk) +add_test(NAME installed-contract COMMAND installed-contract) diff --git a/quality/generator/generate.mjs b/quality/generator/generate.mjs new file mode 100644 index 0000000..d26a6a9 --- /dev/null +++ b/quality/generator/generate.mjs @@ -0,0 +1,145 @@ +import { spawnSync } from "node:child_process"; +import { createHash } from "node:crypto"; +import { + cp, + mkdir, + mkdtemp, + readFile, + readdir, + rm, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const directory = dirname(fileURLToPath(import.meta.url)); +const root = resolve(directory, "../.."); +const config = JSON.parse( + await readFile(join(directory, "provenance.json"), "utf8"), +); +/** Hash immutable producer inputs and complete generated bytes. */ +const hash = (bytes) => createHash("sha256").update(bytes).digest("hex"); +const spec = await readFile(join(directory, "openapi.yaml")); +if (hash(spec) !== config.contractSha256) + throw new Error("Pinned contract checksum mismatch"); +const cache = join(tmpdir(), "1msg-openapi-generator"); +await mkdir(cache, { recursive: true }); +const jar = join(cache, `${config.generatorVersion}.jar`); +try { + await readFile(jar); +} catch { + const response = await fetch( + `https://repo.maven.apache.org/maven2/org/openapitools/openapi-generator-cli/${config.generatorVersion}/openapi-generator-cli-${config.generatorVersion}.jar`, + ); + if (!response.ok) + throw new Error(`Generator download failed: ${response.status}`); + const bytes = Buffer.from(await response.arrayBuffer()); + if (hash(bytes) !== config.generatorSha256) + throw new Error("Generator checksum mismatch"); + await writeFile(jar, bytes); +} +if (hash(await readFile(jar)) !== config.generatorSha256) + throw new Error("Cached generator checksum mismatch"); +/** Recursively inventory only declared generated code, excluding hand-owned tests and package metadata. */ +async function inventory(directory, prefix = "") { + const result = {}; + for (const entry of (await readdir(directory, { withFileTypes: true })).sort( + (a, b) => a.name.localeCompare(b.name), + )) { + const path = prefix + entry.name; + // Descend only into ancestors or descendants of declared generated roots; unrelated authored files stay untouched. + if (entry.isDirectory()) { + // Match an ancestor or descendant of an explicitly declared generated directory. + if ( + config.roots.some( + (item) => + item.startsWith(path + "/") || + path.startsWith(item.replace(/\/$/, "") + "/") || + item.replace(/\/$/, "") === path, + ) + ) + Object.assign( + result, + await inventory(join(directory, entry.name), `${path}/`), + ); + } else { + // Match complete generated roots and top-level Go files while preserving handwritten contract tests. + if ( + config.roots.some((item) => + item.endsWith("/") + ? path.startsWith(item) + : item === "*.go" + ? !path.includes("/") && + path.endsWith(".go") && + !path.endsWith("_test.go") + : item === path, + ) + ) + result[path] = hash(await readFile(join(directory, entry.name))); + } + } + return result; +} +const temporary = await mkdtemp(join(tmpdir(), "1msg-native-generation-")); +try { + const properties = Object.entries(config.additionalProperties) + .map(([key, value]) => `${key}=${value}`) + .join(","); + const result = spawnSync( + "java", + [ + "-jar", + jar, + "generate", + "-i", + join(directory, "openapi.yaml"), + "-g", + config.generatorName, + "-o", + temporary, + `--additional-properties=${properties},hideGenerationTimestamp=true`, + "--global-property=apiTests=false,modelTests=false", + ], + { stdio: "inherit" }, + ); + if (result.status !== 0) + throw new Error(`Generator failed: ${result.status}`); + if (config.postprocess) { + const processResult = spawnSync( + process.execPath, + [join(root, "quality/postprocess.mjs"), temporary], + { stdio: "inherit" }, + ); + if (processResult.status !== 0) + throw new Error("Generated compatibility transform failed"); + } + const expected = await inventory(temporary); + if (!Object.keys(expected).length) + throw new Error("Generator produced no inventoried code"); + const inventoryPath = join(directory, "inventory.json"); + if (process.argv.includes("--write")) { + const previous = await inventory(root); + for (const path of Object.keys(previous)) + if (!(path in expected)) await rm(join(root, path)); + for (const path of Object.keys(expected)) { + await mkdir(dirname(join(root, path)), { recursive: true }); + await cp(join(temporary, path), join(root, path)); + } + await writeFile(inventoryPath, JSON.stringify(expected, null, 2) + "\n"); + } else { + for (const actual of [ + await inventory(root), + JSON.parse(await readFile(inventoryPath, "utf8")), + ]) + if (JSON.stringify(actual) !== JSON.stringify(expected)) + throw new Error( + "Generated drift: review producer then run node quality/generator/generate.mjs --write", + ); + } + console.log( + `Verified ${Object.keys(expected).length} generated ${config.language} code paths`, + ); +} finally { + await rm(temporary, { recursive: true, force: true }); +} diff --git a/quality/generator/inventory.json b/quality/generator/inventory.json new file mode 100644 index 0000000..afee6c8 --- /dev/null +++ b/quality/generator/inventory.json @@ -0,0 +1,241 @@ +{ + "CMakeLists.txt": "0e24dde6742d3ce918ec10daf11b8bd9be846390de8b5b19911180f8d40d145c", + "Config.cmake.in": "823e300531263c9c9aa0b6ba2731c37daa3e9ad385c59d410cfc2347bfae4ca6", + "include/one-msg-sdk/AnyType.h": "a141ad7988c78b2b574d693d8723c7fe37a49c9f5416b013b7779196b2c950f6", + "include/one-msg-sdk/api/CallingApi.h": "2fe35a530a27df0e6e978fb94dd3de703af37cae90e4330374c512e386fb6334", + "include/one-msg-sdk/api/CatalogApi.h": "108806b3b4eff9abb7f2c3a58dbf980ea2cedec1a13ad6dc4cab9d6c715bf451", + "include/one-msg-sdk/api/ChannelApi.h": "01518e06f73e765593e8537725c008d5a454435f8abcbf749bd0aca5d23576ea", + "include/one-msg-sdk/api/FlowsApi.h": "0f1bf28307957ee6af120808b1ddff80fb22496dfc7b79c087ae778fe4d6272b", + "include/one-msg-sdk/api/GroupsApi.h": "b6350dbff0b9752131d78d781bc095d91f5ef01752cc2df03b80c2ed5e31e103", + "include/one-msg-sdk/api/MessagingApi.h": "63fb33a887dc9950c06b702e2d66719dece277a976005dd97e2061640a501b9a", + "include/one-msg-sdk/api/ProfileApi.h": "09fda82ec092c22b7b7576cd2a7d8baa29f3d8d5cb179c2c096dedf71dc0290a", + "include/one-msg-sdk/api/TemplatesApi.h": "cb8f85e12ee971a88b4d8f48383074b6bc0db2b65e71fb0bd7a6af94368739df", + "include/one-msg-sdk/api/UsersApi.h": "654cb4288ed92d3c3b5c207a8e994aaaa51ba2e7e101d0bad4830bd79e2144b4", + "include/one-msg-sdk/api/WebhooksApi.h": "990a64176507ccae1fdc480e44f79f346ff9fee5148310ed50f0d19f9c3f77ac", + "include/one-msg-sdk/ApiClient.h": "d96e6e13fb7e4e251b683832620fa934101e722baebb53d97db694f699ae889e", + "include/one-msg-sdk/ApiConfiguration.h": "519985693faf9dabc9f981c06f229a84625a292e17a5ac9b76188052f671fa97", + "include/one-msg-sdk/ApiException.h": "6c18343e3e6b2b26cd939f35a9d67402a2cbb32442c5c901ada0bbb6011f9006", + "include/one-msg-sdk/HttpContent.h": "4f90899cbbac4733df1c8305c793a846b8f5812efcafd8a3845aa589fa1b35b0", + "include/one-msg-sdk/IHttpBody.h": "725310fabbfca17491c60ea2016b7a482cc3ab69aac6df1138c9e77742b62105", + "include/one-msg-sdk/JsonBody.h": "e6aca23492ebd0e1519cdd6100a1da3e49c116f0d441c3217d956ac6984bf89a", + "include/one-msg-sdk/model/AddTemplate_200_response.h": "8f045a243b07112059e7df4624cb6a70c225376c9b953287fcfb967eea6d4eff", + "include/one-msg-sdk/model/AddTemplate_request.h": "2418eb2819b26f8e3d3a5345df1ec6e10d2828376d6b145272d0d56ec9ac7242", + "include/one-msg-sdk/model/BlockUser_request.h": "fd3e17893f75e794a7cb4bce4582fdfb218b83e9913518672cce41877207c743", + "include/one-msg-sdk/model/CallingSettings_calling_audio.h": "d0c280c683de7301f36ba14b26c3fa4b9b46415f862b37c484b98f9748b4976d", + "include/one-msg-sdk/model/CallingSettings_calling_call_hours.h": "53ce640f64bc4076c02170f4a6001fc4cbcd0d62fc50bff44ad6ed3682586fc0", + "include/one-msg-sdk/model/CallingSettings_calling_sip_servers_inner.h": "751e222abbb554f3c4f24ac05dfe91cc7ff8d82d1100f86e18889b380ea974fb", + "include/one-msg-sdk/model/CallingSettings_calling_sip.h": "41f1dfb91e3f0a4b10c90e60a7e53d4df8958b7103baace6fe453ecbb5eb3d0f", + "include/one-msg-sdk/model/CallingSettings_calling_video.h": "0f1bfb35f6c5d04d436a17eba3c49f312eec36b40da2186a3487abae05c8b17d", + "include/one-msg-sdk/model/CallingSettings_calling.h": "c7f1d5241e91dda4827b84e0af7be07aaa0a5cd0f08e7c5ef0486d92f05dd1db", + "include/one-msg-sdk/model/CallingSettings.h": "00e77419e695be0f135338dd0aadb18f8c0881c94faa2f35386f85f1bfa0334d", + "include/one-msg-sdk/model/ConversationalAutomation_commands_inner.h": "1e8529fea86cf7d412deb8b3bb55c130c7c1084fc540ee94ffdd0a29667ce77f", + "include/one-msg-sdk/model/ConversationalAutomation.h": "186211dae750760258c67be8f5a19ad7a608c21f077bd2154c3bb24f7e58d1be", + "include/one-msg-sdk/model/CreateCommerce_200_response.h": "be83a7cd97f4f3b28bd3e3d910824c65b1c6c1b5575a3169b2273f750c64ee0c", + "include/one-msg-sdk/model/CreateCommerce_request_params.h": "502ed4a14b784eb7fba39410b9cd9cb4a04a0f39a9d35aa852e89d6a295c09fe", + "include/one-msg-sdk/model/CreateCommerce_request.h": "7cc5bd9887313846fcab35f0bd61101c52c56484e1c80f8a64a406d433a6d54f", + "include/one-msg-sdk/model/CreateFlows_request.h": "13ab44628487fd4d45dacfd2f60455b5ef505fa68432be4cead9ed20e5b698f0", + "include/one-msg-sdk/model/CreateGroups_200_response.h": "5ec2c47899b9dcbdd9d8826dc312c84a9ab6c5967d6cd530b27ba4b153c85f55", + "include/one-msg-sdk/model/CreateGroups_request.h": "a9d4dd8b34200c06d1ce41461ab564d375512cc04c3457468633c67364b12edd", + "include/one-msg-sdk/model/CreateGroupsGroupId_request.h": "ba056276272fc2b1bf70b87ad2b12c81bf64279f67b52c47b15feee0fae7ecae", + "include/one-msg-sdk/model/CreateReadMessage_200_response.h": "c1c5a6d2a3298da65c92f3a50ae74be0fbaf3a6fac3cfed51f83676ed8aa549f", + "include/one-msg-sdk/model/CreateReadMessage_401_response.h": "d1e8dcb3302b7efe9231293395c815618f67ec34dd459075c4bdc7f84cd023c8", + "include/one-msg-sdk/model/CreateReadMessage_request.h": "d42fda8fc7ab1a18c596beda44b19f5e80409c65cdbe99e719d0e61637a24559", + "include/one-msg-sdk/model/CreateSettings_request_webhookUrl.h": "c7d470162e0e7daf04160c064d1062805b8dbd9b97e580217a76b249ec414da8", + "include/one-msg-sdk/model/CreateSettings_request.h": "e03895eb744e164becd4ca18c15c41676ad6f7a74531d87911ae485600c3ef4d", + "include/one-msg-sdk/model/CreateUploadMedia_200_response.h": "dcf032b6a0c6846001d54eba613bf295b4800fbfaa6406cc3fbf504aef8b2367", + "include/one-msg-sdk/model/CreateUploadMedia_request.h": "1ab579f1693074bab682a09a06b0b10554872951e387c44d9acac857ccdb1bc6", + "include/one-msg-sdk/model/DeleteFlowsFlowId_200_response.h": "e80c489315d290455956a581aa4b1c62aee421b6685da682e5fd7ed80a13c917", + "include/one-msg-sdk/model/DeleteGroupsGroupId_200_response.h": "0c5ed400e8eec7abd999b6621313df0096a30c31f1c9e30913122852c5d8747a", + "include/one-msg-sdk/model/DeleteMediaLegacy_request.h": "016d33dab61c389d1ef4ec7b42e45bbf20bb7110f97a308068a97ac3b4b41017", + "include/one-msg-sdk/model/ErrorResponse.h": "b838c144542661cb76208118728c91aac81a4fe717571f7c4ba995697ed9f8a0", + "include/one-msg-sdk/model/GetCommerce_200_response_inner.h": "6b4b78ddfb96dfa49e160bdab9fb72a468e4fed5fc55100b15544bce8fd02563", + "include/one-msg-sdk/model/GetMmLiteStatus_200_response.h": "adddce3daf9c6210e91e9a7d92767ea3156f0376dc3d5109500983ea72693d1e", + "include/one-msg-sdk/model/GetStatus_200_response.h": "c81f9b12592f3c3813bcd1c5c341c33bb3d6630e802aa590f271f02eca15c09d", + "include/one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h": "ad6bd8e6e62ec3248f5a54fb2599153b9e31480b99049a4d5a22b24b278ac348", + "include/one-msg-sdk/model/GetWebhook_200_response.h": "45487acea87661b3fe830f808d803195f30cdac7d330acf4f00d746906a58c56", + "include/one-msg-sdk/model/GetWhatsappBusinessEncryption_200_response.h": "e8c20f811e2c2b35940a373838ef75f8a24bc15545c434b11d121612396d496a", + "include/one-msg-sdk/model/InitiateCallRequest_session.h": "da0cd0c83b2e5b73a9c235a3cc682d2d428701fd620b534fae3ed529b139a562", + "include/one-msg-sdk/model/InitiateCallRequest.h": "13e8a19bb3e6f54bc92bd9e481af70f34e201caef0eece874495ac2701f3c5f3", + "include/one-msg-sdk/model/InitiateCallResponse_calls_inner.h": "67386addbe7d9320e78065c119e3ded3d074e0a91fd2e3520f4143ccec53f04f", + "include/one-msg-sdk/model/InitiateCallResponse_response.h": "d377e6f0119747bd3cc7e41a58183eb833afb0f2bd9d662f8090a08714e07059", + "include/one-msg-sdk/model/InitiateCallResponse.h": "ad9b51e36d5430ebf7095db21ca377597c53299eaa41d761841717066b760156", + "include/one-msg-sdk/model/ListBlockedUsers_200_response.h": "b92d3648d8b08fc10f951ee4c01a317ddaa2b621ca20bddab3902f60fec19a5e", + "include/one-msg-sdk/model/ListFlows_200_response.h": "5356cabd3e3036656aacd92f9419b3e2f56389740fc4ca207e71d995dab1f71e", + "include/one-msg-sdk/model/ListMessages_200_response.h": "267afe2bf36b1fca6bf96f91d41c631ece59df65b2729966dece4a510ec9fd10", + "include/one-msg-sdk/model/ListSettings_200_response_webhookUrl.h": "c2e7c54e600fecf2fb7f488b97b15055091cc0e71217159ba273712453622099", + "include/one-msg-sdk/model/ListSettings_200_response.h": "fdb14195383aa6e8b5720490e0d0eeb39ab62f6296fb5d8e0e8fc280b3bb9bfe", + "include/one-msg-sdk/model/ListTemplates_200_response.h": "6f2613e6ce27d68e443eccccfd694afa9c501eeb2f985d72ad7d8c8ce307858c", + "include/one-msg-sdk/model/MessageSentResponse.h": "0dec1e61fcf75a65109b86e6e442e51c5226bca650529f037080cf291bd8d90b", + "include/one-msg-sdk/model/PatchFlowsFlowIdAssets_200_response.h": "66593cc599bd8b5612eba8995196be99663aa8e0d8e12966ad90d2977a9fe9df", + "include/one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h": "76c01e3870e832fe004db3cf3d1ebb0dd7c59e18d2d6fcc81a687583dae7663e", + "include/one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h": "dca8e302de1b095dfbc95edd89f4b88502b5ea3a66d7c6795e39e46940f2ffb3", + "include/one-msg-sdk/model/ProfileInfo.h": "58417fd09d6ba5e0d3dad20649a8498c68aa7d9debde763f4f394af1a92c7fa2", + "include/one-msg-sdk/model/RemoveTemplate_request.h": "8554dc3b714444b93981db0ba2b60c3081fc722eac44f4e196099b1ff616e950", + "include/one-msg-sdk/model/RetrieveMedia_200_response.h": "08d68c26970f3a487713ccff94b1a5317eaa46654682e6ecb51c7161a96694f6", + "include/one-msg-sdk/model/SendAddressMessage_request.h": "12dbf65154203e7a7f4dcc1b8f4010b91b77504ef225fbf97b28b151849fefbf", + "include/one-msg-sdk/model/SendButton_request_sections_inner_reply.h": "92edcb2af3658d3dadceb60e4f1ac09f852b01aa2cad7aa1fbf496930503e2e5", + "include/one-msg-sdk/model/SendButton_request_sections_inner.h": "46ee56eddea4f13e80aa507b25878c7806fc40c5173369184696e558346e81b9", + "include/one-msg-sdk/model/SendButton_request.h": "c80d8b154e9cc3d52a706fcad30f29abaacf8b79dd24364ef03f493e2e372e59", + "include/one-msg-sdk/model/SendCarousel_request_1.h": "eef28c037f47af28084659dc1d2bb9b934eea03745018aed7c403a0d0d41f497", + "include/one-msg-sdk/model/SendContact_request_contact_name.h": "523929229d976f268e8dbeff0957b4f21d1bccdd4d08397bd71c4aaad612839b", + "include/one-msg-sdk/model/SendContact_request_contact.h": "470905f2b57eac19fcd9f1b24801082c7bfeceedbb7c1ded4c52d1b3b7b643d5", + "include/one-msg-sdk/model/SendContact_request_contacts_inner_name.h": "12293c32a029822cc2992c89ac96bf6b03308eb01b1ec5d2b6ddf9ceffe67840", + "include/one-msg-sdk/model/SendContact_request_contacts_inner_org.h": "29c1573f3daa2bb4ad33e09c7fb8d8ebfab213bc3fbafe639d08de26264c57d7", + "include/one-msg-sdk/model/SendContact_request_contacts_inner_phones_inner.h": "37b904920447766af6d1c0e29db5550228d9dd44b8f5e439c99a8758b439db31", + "include/one-msg-sdk/model/SendContact_request_contacts_inner.h": "bf9ae97b6f2c80b0acfa81230f84e07e251c2186933fff10f55949b071eb76b5", + "include/one-msg-sdk/model/SendContact_request.h": "95d050e82ac66cb3206b08b10568b156aac8d26a0cf1de7c78832129581e321a", + "include/one-msg-sdk/model/SendCtaUrl_request.h": "5aed2b3e48af9f71f1d61bfe32f72a8c20dc53d7ad6c3afa35680f0b26f8bf2c", + "include/one-msg-sdk/model/SendFileRequest.h": "48e939d18cdf54bf3a5b4ccfb8af90e8b14d71625277296d7450db7480709779", + "include/one-msg-sdk/model/SendFlow_request_1_header.h": "62b1f643e35eada3646cd85575529243a0ee05870361ffae8e9ef05b4596daf0", + "include/one-msg-sdk/model/SendFlow_request_1.h": "8456cabe5af292eb9741cbc6235d42386b4b9c25ec86e96493dd6f3f1125bf7b", + "include/one-msg-sdk/model/SendFlow_request_header.h": "c3792e79c59e8b3a84db9926d0aa1018722142c36983f1cd64ee9a06ccf0ea70", + "include/one-msg-sdk/model/SendList_request_sections_inner_rows_inner.h": "db95114e98778d0be14ba673f99eb8975f59211df724a86c2d8bb2d7beedb081", + "include/one-msg-sdk/model/SendList_request_sections_inner.h": "3dd04b9cc5c7ac6f28031a10bb1510b82fe4787ac04331d38971164d3c1b9e6f", + "include/one-msg-sdk/model/SendList_request.h": "bdf781c8560a7f8632444b1db36ffc3b5ff7278fb77e56cd9b7c118590bf5cfb", + "include/one-msg-sdk/model/SendLocation_request_1.h": "3fe4d80ea61638568bf861195e5e1521bbcc7753c0a83f8ac9a5e339d88f04b5", + "include/one-msg-sdk/model/SendLocationRequest_request.h": "8ea3fe036ff67373a4eb18b8e107f939132ac62eb29f98d9f4d3c49185860ecc", + "include/one-msg-sdk/model/SendMessageRequest.h": "806e6ee19f7a636aeb77de1bdf8b96cf2714a0ecd0ab067cc3aaf2d00272b1f2", + "include/one-msg-sdk/model/SendOrderDetails_request_language.h": "672821791ee82d09a5599de623d758c59d60301513d5a8b95a645fa669bc61d8", + "include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner_amount.h": "8c6e81623bc0c241574401c93d78e2652ce7f39ffc7aaa8c34563b7ff1cc6cc6", + "include/one-msg-sdk/model/SendOrderDetails_request_order_items_inner.h": "efbbc6a2f0e558d6bc9698933e45ed740e538c6dcf5e822e295d9e680e86d889", + "include/one-msg-sdk/model/SendOrderDetails_request_order.h": "96eba7a52dd22e3fdaa486f59a4815aeea922bc283e44694a9b83b5f879c5a98", + "include/one-msg-sdk/model/SendOrderDetails_request.h": "9e0ca46fcc627adf0b9c06cbfcfdb2f586769faa5ec830e2daa67191437cc383", + "include/one-msg-sdk/model/SendPaymentRequest_request.h": "358ea90a7dd7d34602ae5cdbcaea0b53df6ea1abffa17cf642526212f265ee66", + "include/one-msg-sdk/model/SendProduct_request.h": "bfe0df65aa731707b5a592d48a80dbe9bad3a4e57b29970f830b829f5575ee25", + "include/one-msg-sdk/model/SendReaction_request.h": "886497fa6496b3d6ad12841a89dc7b19e5ab14dd05bccd909f56f523f2592253", + "include/one-msg-sdk/model/SendSticker_request.h": "3adfd6f09539549ae5e1ce1c23fa40437b51b8d9180c8f733414fd3766417436", + "include/one-msg-sdk/model/SendTemplate_request_language.h": "91bc59b03a1c9a4e83bcecd558928b50a9ce4a89a8ccb61db5ba44dd09dbe77a", + "include/one-msg-sdk/model/SendTemplate_request.h": "944fbf1c9cc2846086a231fd28cd4f4aa1a12bf05110484f63ce12c333d54e93", + "include/one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h": "57d2c633793ebbbc60e621da879b9214920a854391f0cef1105713fb66928b46", + "include/one-msg-sdk/model/SetWebhook_200_response.h": "942f9d9dad420382137e45a16c8c680460345c0e18a0ab43bf8ca616eb9ef280", + "include/one-msg-sdk/model/SetWebhook_request_webhookUrl.h": "31cc9dc09c2cde509a1c4893380dc67a538bbc9f0aed644cc46a1305156f59f6", + "include/one-msg-sdk/model/SetWebhook_request.h": "3de035bbf8756e017d6abb258540742d8dccc57ad70671d43f416c89c4ba31de", + "include/one-msg-sdk/model/SetWhatsappBusinessEncryption_request.h": "3ed9e63c83a91bc5c42eb33d858c1565ce6d039bfde77665fda6e20689db1249", + "include/one-msg-sdk/model/SuccessResponse.h": "41f5e597070745517f92da8ca3964d010368ba866afc10b2d8f1ffe0f61fed61", + "include/one-msg-sdk/model/UpdateCallingSettings_200_response_response.h": "86539312da5242d083d38d85ad2279c44cec4b8515ad192c9124649932b75961", + "include/one-msg-sdk/model/UpdateCallingSettings_200_response.h": "e61f900f289953f0d33e6e9a526e06aa5d4d859cdf86df8d534474faaa0ff623", + "include/one-msg-sdk/model/UpdateMe_200_response.h": "15f494fd08d70c1a8f219fd31acfd2c6bc8861cfe2fc09ff10f16a44833e7cfc", + "include/one-msg-sdk/model/UpdateMe_request.h": "7a855244ffd3168b8d8a330ba9a4167836a0e9012b03c45393bb9b377ccdfedc", + "include/one-msg-sdk/model/WebhookUrlStatus.h": "bf10b21e3586ef0991c95a1b2622bf1f838834299d1b18f64f3cf8e759224797", + "include/one-msg-sdk/ModelBase.h": "fee3264e511a8e4eda63668ebcac5accdba29a677bf3c3fd48fd956134076ba7", + "include/one-msg-sdk/MultipartFormData.h": "785db833adec44ab426de8c2f344f08145b9442900e172d70196d4242963afef", + "include/one-msg-sdk/Object.h": "4bd1214492b10599231e67fe61ab21c332b90fcfe34ef50af9829803dd2fd86f", + "src/AnyType.cpp": "08476bd1026cf7865766a8d32c7136f65dcbdf6eb9c6e629835f467feae613ad", + "src/api/CallingApi.cpp": "9c10015cd985d017f611c8489198488e8e22e3d93602ce2beb6a1b400c484c0e", + "src/api/CatalogApi.cpp": "72ebdcc7ace798bee8b8e06f531a4c9d5732464626d76e0cc870121a1e372667", + "src/api/ChannelApi.cpp": "e91c94b81563c681efd3dd8da65e62f534266e2b64bea933ccfb092118ffb9e8", + "src/api/FlowsApi.cpp": "c8401f2a8ff25ef22c07bf220c10ae45c228dd1e06a090c396ba873abe0695e6", + "src/api/GroupsApi.cpp": "7ae17adcf8d5c3398f5bbe3ff2ce0c0762d986f7f2f7d1f558bfa9f216e41281", + "src/api/MessagingApi.cpp": "01f01e439887653661cd267e1e1557411fe04a4d9aa305a9726ca837ca7ab1d8", + "src/api/ProfileApi.cpp": "ff527af1aab2b47e554eee73e0a18180c75e7dcc86f84eb28d55a4bbfbb37f9b", + "src/api/TemplatesApi.cpp": "5dea6ec8299d44d93f47906d895f014bf33fbbda1a6cd94852d208b1c553042a", + "src/api/UsersApi.cpp": "a364b9997e898c808887038ffaaab9c5f40efd01c9e79d35a8e961d01c247841", + "src/api/WebhooksApi.cpp": "15c33bcfdd3de1d5f2c2e68057792adcb126a7931b0adf88764fe79c495bf715", + "src/ApiClient.cpp": "f26755344f1ebd81e5d3c72b0d60f858632cf5ad71fd21dc777770bae82b1598", + "src/ApiConfiguration.cpp": "323d2aaf4c52f89fc2e35c5418a22ed72602bc4e4a93f79e64be1c06be353f98", + "src/ApiException.cpp": "3fd146e7e8376631f448084716743cdb4dcc9be02cae92a5f5b0fb651b2e6865", + "src/HttpContent.cpp": "45a26eb4c42d07dfc2bef1ad1d2a800681ef9a65e82896529cc7fed2766b6535", + "src/JsonBody.cpp": "377109619603df3a51482eca2233eda3f128bacb0d22d951d379c36913806954", + "src/model/AddTemplate_200_response.cpp": "b86b7e94e62dcc9c461577218c0703cc05caba189a3478484a011584943876ab", + "src/model/AddTemplate_request.cpp": "77ed419b696ef7b200262c153c542be1d31530ecbd07258cc6044f7a27c65843", + "src/model/BlockUser_request.cpp": "75c6bf46a1a9b0a9932e67fdbf1a5b0dcc025e021e3940b39b948e0edfe391da", + "src/model/CallingSettings_calling_audio.cpp": "cb01f5774acf0aded42d7c6e5d1553b8e2de1b33d31ac5ca76e36d3d0dad0c0d", + "src/model/CallingSettings_calling_call_hours.cpp": "4d2ade9d333b04c4eff999ff4dee3153735d3fc9d1e4aa61c74f73b75780306b", + "src/model/CallingSettings_calling_sip_servers_inner.cpp": "e661c905e361d91f8946026d84ce8d934a1a546a7ba191dc3e37392733f77d5f", + "src/model/CallingSettings_calling_sip.cpp": "f10cfd93df778afc9ce2ed923a09e3c45a97e6eed0680defff799e8c3a571dc2", + "src/model/CallingSettings_calling_video.cpp": "eb5f7b1e240ef1d8b99080acbe1b1277ca16930a802142c712165eeb634f6cd4", + "src/model/CallingSettings_calling.cpp": "8da28d3966e3a52ea8ef6c02522c0c145c5934f0d5bab14fb0e8ffeec6e3ecf1", + "src/model/CallingSettings.cpp": "da6cc5e106c2b5fbfe3dea07efa72c3bba611bce5576ab69d1d313bcb2037f38", + "src/model/ConversationalAutomation_commands_inner.cpp": "1cd17cca1a5db223d74cb07136d9b5b65ee7dd0dfb18bf5eb8ccfe175712146d", + "src/model/ConversationalAutomation.cpp": "6cd0717c7a8716fadc64aa660bb7c7aeb79b96dce4fd5f30079140ccce394af1", + "src/model/CreateCommerce_200_response.cpp": "b8f71154374a3facc90092cd88eb0a00c6512d7c2a5bf74426776976a77725f8", + "src/model/CreateCommerce_request_params.cpp": "b0f454b04ad433a8328195faa8530343b423acd836a2f460f130cb0a88df74a2", + "src/model/CreateCommerce_request.cpp": "2a67f6a0a44a7b3ea8818eece013a3e0059c8c7b0a138faddb53361ef685ac30", + "src/model/CreateFlows_request.cpp": "53ca8dd2588012df1fb43345159e22bfcbb2d841603f901b5b2e5700f0d56436", + "src/model/CreateGroups_200_response.cpp": "db378938c4ce7978de849e4166a23021fc69198af72c7c0c6dc70d8c760641e5", + "src/model/CreateGroups_request.cpp": "323ebe63db333670fc0d865afc9fd41487e4615d964e22953937491df41d12b1", + "src/model/CreateGroupsGroupId_request.cpp": "7fd0ca8c5be8d9b6743e2d1e89d469ae6369a5e66e9efa0ddc5d336c6496669c", + "src/model/CreateReadMessage_200_response.cpp": "2cf49c703bddaa7d4aa611e253bd1dbec2eed20a19e48922b34cd85908e0c136", + "src/model/CreateReadMessage_401_response.cpp": "73ef2c7b9c34e6b98f6af8c09aeb10f0aa850d7c77084849b78576c53641d600", + "src/model/CreateReadMessage_request.cpp": "30e07c3cdecbe0abc0da118cf96622c9bf4f4fd631e0302390859987c83cbda7", + "src/model/CreateSettings_request_webhookUrl.cpp": "5da6c0b6593eaba0fb279f8a72fb5c4fe8f5a6d5fb4cec792721ec33dc51c80d", + "src/model/CreateSettings_request.cpp": "d96c4a3cd4f578d070ea35891cc108d8956460db01a5751edbc8699a7874140a", + "src/model/CreateUploadMedia_200_response.cpp": "c1d759079f91a6d53bfd7a5fa11cc2b772bc9797380e3bac19063858dc393104", + "src/model/CreateUploadMedia_request.cpp": "3ca662aed20c42a7c4035df5968645b0f3657ee0bd7724b66d3fc7ae8a12adf9", + "src/model/DeleteFlowsFlowId_200_response.cpp": "45a9e322c35d55462e6255884b06d854eab1725eacae1889982b4fdfe0f8c122", + "src/model/DeleteGroupsGroupId_200_response.cpp": "6d977ed8715d0716c967f258a308fdb45498b14a98bed33715aace6b5f1d1ac2", + "src/model/DeleteMediaLegacy_request.cpp": "f547a37f1b6f01fba7292018d60ad51b2dbac9ffdaf1eb4cdcb28b6af25ce05f", + "src/model/ErrorResponse.cpp": "787a5a169a0e27d12688066ae087616a4cc2fe6bbfcac2d78797fec1b9f182d3", + "src/model/GetCommerce_200_response_inner.cpp": "796449ef0023fe2de5f2ec0e0f4ffd87a25e5552fa52a2df179c494d84f14bca", + "src/model/GetMmLiteStatus_200_response.cpp": "934e861b0a6dc4b4363bbece85368397afbcb51cb42e3105a127028e3333c14d", + "src/model/GetStatus_200_response.cpp": "4c7f634977ee20675f0203c5af9732aa57d0247e6581e15cca40354b75d868ff", + "src/model/GetWebhook_200_response_webhookUrl.cpp": "560ef3e2d242ed219bd7e4d0418e9cb16da378d9c373d532b0022c85aab5cbf9", + "src/model/GetWebhook_200_response.cpp": "ee65ec4555a444ea5b5c5def111bcd9463974d9ce99ad677ab8d3dbb4a50f7cc", + "src/model/GetWhatsappBusinessEncryption_200_response.cpp": "0d8dd70ca4504608ccfa7bb57a135852f34da5cd89e8c1d19f77a76cde2a44df", + "src/model/InitiateCallRequest_session.cpp": "a415eb5a0fd2d9755b4f848fa97c58a8bb2e038e876111e6636c6059dd92aefb", + "src/model/InitiateCallRequest.cpp": "29696771d2cd9236aad96cc68b91c1a290733159cc920208754e6fc9363a0eb4", + "src/model/InitiateCallResponse_calls_inner.cpp": "96e52d40f1be9ba03161c991f71d2f5e1dfc463d103ac88169ff78de50d13a74", + "src/model/InitiateCallResponse_response.cpp": "a46e744e67710cb6663123b5759d196dd0b0646115355b6bf85e062c9a17131f", + "src/model/InitiateCallResponse.cpp": "a7025447055b002464ea8bce89bb23f8ac7c126db1f3bb2c4daa12e97e5e08fd", + "src/model/ListBlockedUsers_200_response.cpp": "49237e6ded6bcdd7588261b2572d817986d351b9139fee7f29c8cd6ed34e8c82", + "src/model/ListFlows_200_response.cpp": "83b8b8f6f1d3fc064faafe1bee42c841b87937fc19623a4465695200f64fbfc5", + "src/model/ListMessages_200_response.cpp": "00fa0cbc574ae4475f47bbf20d0ef30f620f9409328cb7d719a6f18d2cc8b746", + "src/model/ListSettings_200_response_webhookUrl.cpp": "f3a219b788bca9dd7c2255537ebd91ce187689d254b14d998e332104ea0f6e16", + "src/model/ListSettings_200_response.cpp": "be39b52599dd90ed4981cabf770c367439991efdf2b6e1b85fcfe1223e2107f6", + "src/model/ListTemplates_200_response.cpp": "5774541020f36ca16967e9a877a68af61c8310339acea5118ee35a8294eeaec2", + "src/model/MessageSentResponse.cpp": "a47ecb13487764d4c345abc120506c30acd0f1c0e5f881ce1f6902ea82dc2f53", + "src/model/PatchFlowsFlowIdAssets_200_response.cpp": "19f7366f373aa0db32a732c9466b2f72f5915182be89b2add4ac676915d14dd0", + "src/model/PatchFlowsFlowIdAssets_request.cpp": "3b8dc74bcee2f4211225c59e43b9eddd52494d31501b430e1b63dc6416285932", + "src/model/PatchFlowsFlowIdMetadata_request.cpp": "cfbbb797027b82ed36a77800c0aceb900881af8f48eab36c829f0749548f9e75", + "src/model/ProfileInfo.cpp": "1f07f48f12c98560d8e85df90d4748706ea7e24ff4a4192041b02e09e8ff34da", + "src/model/RemoveTemplate_request.cpp": "4bc98af30bb75463879b760991f90884706b3ee961d7d3513265f6b9700dd56f", + "src/model/RetrieveMedia_200_response.cpp": "a75be646de64d966657eaee5ad43b0d342f840fa5f7ebe2dcb206232e0759d81", + "src/model/SendAddressMessage_request.cpp": "788ac68818e26b81413242fb83b9b399b9094fe6762ce192d0b1cfb6db0dd5e0", + "src/model/SendButton_request_sections_inner_reply.cpp": "fb47cd69aa0a357cf21a35f4f9f4f372f820120e020e7e67c8563d759f60ed9b", + "src/model/SendButton_request_sections_inner.cpp": "d0f224b14e501fd843c3db933b6fe45a60a6b7ba7bbce560129f832544ea6cd1", + "src/model/SendButton_request.cpp": "411e55d16dd4e98448e4844e5fe19759540ed06f3fc96044e805b9786f0a71b4", + "src/model/SendCarousel_request_1.cpp": "9247e8ad5a4429077bb98f96d2bf5beb9a3ce437a13c74f2521ce8e20bf225ff", + "src/model/SendContact_request_contact_name.cpp": "a05a913303701ddb5d18ec8ac64b05019bb1cf0fad57391eed6f9f8e0e166518", + "src/model/SendContact_request_contact.cpp": "320b1b27519c1a55069135893b6a9110ea3bcefed9fa43c40326149d1d302f06", + "src/model/SendContact_request_contacts_inner_name.cpp": "ef7f644e08cba6e05a5626736be69ac8762c189a28ee8a9110365f099adeb43c", + "src/model/SendContact_request_contacts_inner_org.cpp": "cafce1cb28e354221700bf48e16ca44ac12e8f462e7f2a230afb4265422019f6", + "src/model/SendContact_request_contacts_inner_phones_inner.cpp": "733c2fa93d656ae16a2bd5ac0ae0a52d2ae74411d15ad7b0863281b689b5afcf", + "src/model/SendContact_request_contacts_inner.cpp": "1e0b45bd3a1667fd5f24dc068bf4afbcce0c30b5d60530e39e0e25676030c0a3", + "src/model/SendContact_request.cpp": "32837801f419eda24da3a08c82325e12411ab40e106d076053b6a5e24e960088", + "src/model/SendCtaUrl_request.cpp": "8c0a8e5229bc3189521fedf5dd84f77c788eb825830062ad35cfc4f5cd75f8ad", + "src/model/SendFileRequest.cpp": "c7ebbcf9fa667188c097a3a740307389d9af2102e43e8e470fd67acaef5da0c3", + "src/model/SendFlow_request_1_header.cpp": "0f1c2505df25333f517d68d50d7c80c1b9b30612eee650578ceb801b54d537fa", + "src/model/SendFlow_request_1.cpp": "2b3c0710deb78a33de1bdc268f2a323fe2bb00218f8048ccb6c923c6d618767e", + "src/model/SendFlow_request_header.cpp": "94671269c48a9fc2f6f664b44d8f40466fa4cd744326411adabf2dc02ebe7548", + "src/model/SendList_request_sections_inner_rows_inner.cpp": "bc64beb411ab6ba33441cd80f1be89e7622d77b273602840a0ba1a68865c5b2c", + "src/model/SendList_request_sections_inner.cpp": "0c704399ec538c78b2f28d8dde9c0323038499dc0489cfddfbe675315652e1d7", + "src/model/SendList_request.cpp": "1a2e09243c62ccf6b4878546416a3650143fee14c016e8e9c46125869c3f6ee7", + "src/model/SendLocation_request_1.cpp": "ed3564f914eb84559f4743727f05f95b66357a455dacc46dfbe66ce584beb68e", + "src/model/SendLocationRequest_request.cpp": "569256bcd0ff335eff32fbaa513e4a41f9aaf735afc74e71e697d5dc014b166b", + "src/model/SendMessageRequest.cpp": "76491177cdb30e3eacef352be95f52b0ab889677c6c092548668f3d15b0909b0", + "src/model/SendOrderDetails_request_language.cpp": "81c294792fbee725bcf11b6dc3a08686c8aedbdf05a8993ed9b3c6cd7f884e92", + "src/model/SendOrderDetails_request_order_items_inner_amount.cpp": "3b8d9962d02795fc45502ccd0b34c75199bb690a1a65fdec66057cd6c3a89e84", + "src/model/SendOrderDetails_request_order_items_inner.cpp": "ba60cf1a1299d0eac0aea87b742aa1f960bf44d30ab83318f75c6f9778213bd9", + "src/model/SendOrderDetails_request_order.cpp": "82ee615994af1630f410ba3f421f95bc480cdb5584c6807c80fe22e3579e6424", + "src/model/SendOrderDetails_request.cpp": "6a8e6e39bcf72c02230adf1ea459dc67ae3b08d4eab53e46645c9ab3e8ac7481", + "src/model/SendPaymentRequest_request.cpp": "86cc21f46c4ed02a4ad36c1127dae8336046f1d092a045719063fe237c1ee9e2", + "src/model/SendProduct_request.cpp": "725db4e1b4525fb5b14d436afbbcb5fac35f6d521e02404df6ff16d0c0974cbc", + "src/model/SendReaction_request.cpp": "d589724a9ac0397b030caecca0c33d138fbc21f042354af13f7dbd7430b39409", + "src/model/SendSticker_request.cpp": "27164a3dbe954d771325c16a37f9d6746e9975c2a01085c305441bc776619763", + "src/model/SendTemplate_request_language.cpp": "6bead69864ae8257d76f4a054abfc81a57b2ccb564f112dba5e4ec9e43a70cad", + "src/model/SendTemplate_request.cpp": "6ee955fbf0332a42c8bd70b828c0ccf44394b7a06ce7e35352fde68606a477ce", + "src/model/SetWebhook_200_response_webhookUrl.cpp": "cfb57601000c9543b41ae2d1da4d695650e38c16aa84701d5e4fdfe81179d438", + "src/model/SetWebhook_200_response.cpp": "2e43908a9c3d51dce746d8e3bdac9487c03d2f1fa014cbf5277d6e80af6f7933", + "src/model/SetWebhook_request_webhookUrl.cpp": "f73e1deca85b51370f16a7b49d132115723e56fb8d5c8e6892a2a3c95cdfef9a", + "src/model/SetWebhook_request.cpp": "b91c2d10de6d0ba4fc4dc07db588a227154b6e836b6eaa1d74a18077657224ae", + "src/model/SetWhatsappBusinessEncryption_request.cpp": "e9f3146bb569bd64dcca898b58cf747b43f29ab17cb56a3573a977570e401ec7", + "src/model/SuccessResponse.cpp": "f674a06cf818facee4ed2bb6231053af598ec6587a9ea1cf9cffe7f46470d13b", + "src/model/UpdateCallingSettings_200_response_response.cpp": "6b9f154404fb3854dad0c7c117d249bbb0ddf2d83392a52aa255dc110a524170", + "src/model/UpdateCallingSettings_200_response.cpp": "20e28fc96129a8e2d3b42f09c6de7185790a2e94189d22667f46627111e94689", + "src/model/UpdateMe_200_response.cpp": "66aff9251eeeac52a963163d5480aa7988d53734fa4127caaada967708c83b23", + "src/model/UpdateMe_request.cpp": "3b8034972dbe8cc2951b1c3b1d2d5a2368fa6a57b600838ea8c81ff1368e2440", + "src/model/WebhookUrlStatus.cpp": "79ea24cf04c806cf5142c86bbd2251546944bfd89174c1f8d9ecbbfacb4869e4", + "src/ModelBase.cpp": "1c3e63cf0cdd960e08e1058d0b13474845655fa50b4f2de42c16b5756f66f047", + "src/MultipartFormData.cpp": "3b8e7caa4bdf6683a5334d0e7f22c7d8e64c418e12a49ef41cbb4be3a03218ce", + "src/Object.cpp": "a3b9847641c378696e74f1b5adf881d27a19a70a712cd52823539148d437dba4" +} diff --git a/quality/generator/openapi.yaml b/quality/generator/openapi.yaml new file mode 100644 index 0000000..ebed642 --- /dev/null +++ b/quality/generator/openapi.yaml @@ -0,0 +1,4621 @@ +openapi: 3.0.3 +info: + title: 1MSG WhatsApp Business API (Public) + description: > + Public client API for sending messages, managing groups, flows, and + templates. + + + This is the API exposed to end customers via platform.1msg.io + + + **Authentication:** Pass the channel token in **one** place. The API checks + + JSON body (`token`), then query string (`?token=`), then + + `Authorization: Bearer` header (preferred in production). + + + **Documentation:** + https://help.1msg.io/platform-1msg/getting-start/quick-start + + **API Docs:** https://docs.1msg.io/ + version: 1.0.0 + contact: + name: 1MSG API Support + url: https://help.1msg.io + email: support@1msg.io +servers: + - url: https://api.1msg.io + description: Production + - url: https://api-stage.1msg.io + description: Staging + - url: http://127.0.0.1:3050 + description: Local development +tags: + - name: Messaging + description: Send messages, files, templates, and other content + - name: Users + description: Block, unblock, and list blocked WhatsApp users + - name: Profile + description: Channel profile information (read and update) + - name: Channel + description: Channel status and automation settings + - name: Catalog + description: Catalog and cart commerce settings (`GET`/`POST /commerce`) + - name: Groups + description: Create and manage WhatsApp groups + - name: Flows + description: WhatsApp Flows (interactive forms) + - name: Templates + description: Get and manage message templates + - name: Webhooks + description: > + Client webhook URL configuration (`GET`/`POST /webhook`). + + + Auto-disable is **per URL**, not per channel. Prefer `webhookStatuses` on + + `GET /webhook` / `GET /settings`. Top-level `haveDisabledWebhooks` means + at + + least one configured URL is sticky-disabled; live URLs still receive + events. + - name: Calling + description: > + WhatsApp Calling API (beta) — VoIP **signaling** proxy. + + + 1msg does **not** host media, store call history, or store recordings. + + You need your own WebRTC or SIP stack. + + + ### Prerequisites + + - Meta Calling enabled on the number (Cloud API; not COEX) + + - Paid channel — trial / `subscriptionBlocked` → **403** plain text + + - Webhook URL configured (`POST /webhook`) for `calls` events + + + ### Inbound (user → business) + + 1. Webhook `type=calls`, `event=connect` — take `call_id` + SDP **offer** + + 2. Optional: `POST /initiateCall` `action=pre_accept` + WebRTC **answer** + SDP + + 3. `action=accept` + WebRTC **answer** SDP, or `action=reject` + + 4. Later `event=terminate`, or `action=terminate` to hang up + + + Answer within ~**30–60s** or Meta ends as unanswered. + + + **Critical:** `accept` / `pre_accept` need a **WebRTC-generated SDP + answer**. + + Do **not** echo Meta's offer. Postman/curl alone cannot establish real + media. + + + ### Outbound (business → user) + + 1. Send Call Permission Request (CPR) — template or interactive + + 2. Wait for permission reply on the **messages** webhook + (`call_permission_reply`) + + 3. `POST /initiateCall` `action=connect` + business SDP **offer** + + 4. Apply Meta's SDP **answer** from the `calls` connect webhook + + + Meta limits (summary): permission ~7 days; up to 5 calls / 24h / user; + + max 2 CPR / 7 days; auto-revoke after 4 unanswered. + + + ### Webhooks (`type=calls`) + + Passthrough of Meta `field=calls` plus `type`, `instanceId`. + + Events: connect (offer or answer SDP), statuses (`RINGING` / `ACCEPTED` / + + `REJECTED`), terminate. CPR replies use the messages path, not + `type=calls`. + + + See operations below for request bodies and examples. +paths: + /me: + get: + summary: Get Profile Info + description: > + Return the WhatsApp Business profile for this channel: About, address, + + description, email, phone, websites, industry (`vertical`), and profile + photo URL. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Profile information + content: + application/json: + schema: + $ref: "#/components/schemas/ProfileInfo" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Profile + operationId: getMe + post: + summary: Update profile info + description: > + Update WhatsApp Business Account profile fields. At least one of + + about, description, email, photo, address, vertical, websites is + required. + + Blocked when the channel subscription limit is exceeded. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + about: + type: string + description: Profile About section (WhatsApp status text) + example: Available 9–18 + address: + type: string + description: Business address shown on the profile + description: + type: string + description: Business description (max 256 characters) + email: + type: string + description: Business email shown on the profile + example: support@example.com + vertical: + type: string + description: Industry of the business + photo: + type: string + description: HTTPS URL or data:image/...;base64,... payload + websites: + type: array + items: + type: string + description: Business website URLs + additionalProperties: true + example: + about: Available 9–18 + email: support@example.com + responses: + "200": + description: Profile updated + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: success + additionalProperties: true + example: + result: success + "401": + $ref: "#/components/responses/InvalidToken" + "422": + description: Wrong request (no updatable fields) + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Profile + operationId: updateMe + /sendMessage: + post: + summary: Send a Message + description: > + Send a message to an existing chat. (Only if the dialogue has an Open + Session). + + The message will be added to the queue for sending and delivered even if + the phone + + is disconnected from the Internet or authorization is not passed. + + + Only one of two parameters is needed to determine the destination - + chatId or phone. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/SendMessageRequest" + application/json: + schema: + $ref: "#/components/schemas/SendMessageRequest" + example: + body: Hello World + phone: 12020721369 + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendMessage + /sendFile: + post: + summary: Send a File + description: > + Send a file to an existing chat. (Only if the dialogue has an Open + Session). + + Only one of two parameters is needed to determine the destination - + chatId or phone. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/SendFileRequest" + application/json: + schema: + $ref: "#/components/schemas/SendFileRequest" + example: + phone: 12020721369 + body: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf + filename: dummy.pdf + caption: Here is the file + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendFile + /sendLocation: + post: + summary: Send a Location + description: > + Send a location to an existing chat. (Only if the dialogue has an Open + Session). + + Only one of two parameters is needed to determine the destination - + chatId or phone. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + required: + - lat + - lng + properties: + lat: + type: string + description: "Latitude of the location. Example: 45.018337" + lng: + type: string + description: "Longitude of the location. Example: -73.968285" + address: + type: string + description: "Address of the location. Only displayed if name is present. + Example: 9766 Valley View St., New York, NY 10024" + name: + type: string + description: "Name of the location. Example: Facebook HQ" + quotedMsgId: + type: string + description: Quoted message ID (Cloud API) + chatId: + type: string + description: "Required if phone is not set. Chat ID from the message list. + Examples: 12020721369@c.us or + 120363046942338209@g.us(group)" + phone: + type: integer + description: "Required if chatId is not set. A phone number starting with the + country code. USA example: 12020721369." + application/json: + schema: + type: object + required: + - lat + - lng + properties: + lat: + type: string + lng: + type: string + address: + type: string + name: + type: string + quotedMsgId: + type: string + chatId: + type: string + phone: + type: integer + example: + lat: "45.018337" + lng: "-73.968285" + name: Facebook HQ + address: 9766 Valley View St., New York, NY 10024 + phone: 12020721369 + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendLocation + /sendContact: + post: + summary: Send a Contact + description: > + Send a WhatsApp contact card. + + + Preferred simple body (legacy-compatible): + + + ```json + + { + "phone": "79001234567", + "contact": { "name": "Lida", "phone": "+79181976551" } + } + + ``` + + + Cloud API shape also works: `contacts` is an array of objects with + + `name.formatted_name` and `phones[].phone` (E.164 string, **not** a + timestamp). + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + requestBody: + content: + application/json: + schema: + type: object + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + contact: + type: object + description: Simple contact card. Use this or `contacts`. + required: + - name + - phone + properties: + name: + description: Display name (string) or Cloud API name object + oneOf: + - type: string + - type: object + additionalProperties: true + phone: + type: string + description: Contact phone in E.164 (`+79181976551`), not a timestamp + email: + type: string + org: + type: object + additionalProperties: true + url: + type: string + contacts: + type: array + items: + type: object + properties: + name: + type: object + properties: + formatted_name: + type: string + first_name: + type: string + last_name: + type: string + middle_name: + type: string + suffix: + type: string + prefix: + type: string + birthday: + type: string + addresses: + type: array + items: + type: object + additionalProperties: true + emails: + type: array + items: + type: object + additionalProperties: true + org: + type: object + properties: + company: + type: string + department: + type: string + title: + type: string + phones: + type: array + items: + type: object + properties: + phone: + type: string + description: E.164 phone (`+79181976551`). Not a timestamp. + type: + type: string + wa_id: + type: string + urls: + type: array + items: + type: object + additionalProperties: true + example: + phone: "{{testPhone}}" + contact: + name: John Doe + phone: "+1234567890" + operationId: sendContact + /sendList: + post: + summary: Send List Message + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + requestBody: + content: + application/json: + schema: + type: object + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + body: + type: string + buttonText: + type: string + action: + type: string + sections: + type: array + items: + type: object + properties: + title: + type: string + rows: + type: array + items: + type: object + properties: + id: + type: string + format: utc-millisec + title: + type: string + description: + type: string + example: + phone: "{{testPhone}}" + body: This is a list message + buttonText: Click me + action: Action + sections: + - title: Section 1 + rows: + - id: "1" + title: Row 1 + description: Description for Row 1 + operationId: sendList + /sendButton: + post: + summary: Send Reply Buttons Message + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + requestBody: + content: + application/json: + schema: + type: object + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + description: Optional Cloud API wamid to quote + body: + type: string + footer: + type: string + header: + type: object + additionalProperties: true + description: Optional interactive header (text/image/video/document) + buttons: + type: array + items: + type: object + description: Legacy alias for sections (`[{id,title}]`) + sections: + type: array + items: + type: object + properties: + type: + type: string + reply: + type: object + properties: + id: + type: string + format: utc-millisec + title: + type: string + example: + phone: "{{testPhone}}" + body: This is a buttons message + footer: Footer + sections: + - type: reply + reply: + id: "1" + title: Button 1 + operationId: sendButton + /sendLocationRequest: + post: + summary: Send Location Request Message + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + requestBody: + content: + application/json: + schema: + type: object + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + body: + type: string + example: + phone: "{{testPhone}}" + body: Text + operationId: sendLocationRequest + /sendFlow: + post: + summary: Send WhatsApp Flow Message + description: > + Send Interactive WhatsApp Flow message to an existing chat. (Only if the + dialogue has an Open Session). + + Only one of two parameters is needed to determine the destination - + chatId or phone. + + + Use this method to send a published WhatsApp Flow as a service + (interactive) message. + + If the 24-hour window is closed, send a template with a FLOW button via + /sendTemplate. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + required: + - body + - flowId + - flowToken + - flowCta + properties: + body: + type: string + description: Flow message body text + header: + oneOf: + - type: string + - type: object + description: Flow header (string or text header object) + footer: + type: string + description: Footer text + flowId: + type: string + description: Published Flow ID + flowToken: + type: string + description: Flow token generated by the business + flowCta: + type: string + description: CTA button text + flowAction: + type: string + enum: + - navigate + - data_exchange + description: Flow action type + flowActionPayload: + type: object + description: Required for flowAction=navigate (screen is required). Ignored for + data_exchange. If data is provided, it must be a non-empty + object. + flowMessageVersion: + type: string + description: Flow message version (default "3") + mode: + type: string + enum: + - draft + - published + description: Flow mode (draft or published). If omitted, provider default + applies + flowActionData: + type: object + description: Shortcut for flowActionPayload.data (optional) + flowActionScreen: + type: string + description: Shortcut for flowActionPayload.screen (optional) + quotedMsgId: + type: string + description: Quoted message ID (Cloud API) + chatId: + type: string + description: "Required if phone is not set. Chat ID from the message list. + Examples: 12020721369@c.us or + 120363046942338209@g.us(group)" + phone: + type: integer + description: "Required if chatId is not set. A phone number starting with the + country code. USA example: 12020721369." + application/json: + schema: + type: object + required: + - body + - flowId + - flowToken + - flowCta + properties: + body: + type: string + header: + oneOf: + - type: string + - type: object + footer: + type: string + flowId: + type: string + flowToken: + type: string + flowCta: + type: string + flowAction: + type: string + enum: + - navigate + - data_exchange + flowActionPayload: + type: object + flowMessageVersion: + type: string + mode: + type: string + enum: + - draft + - published + flowActionData: + type: object + flowActionScreen: + type: string + quotedMsgId: + type: string + chatId: + type: string + phone: + type: integer + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendFlow + /sendReaction: + post: + summary: Send Reaction + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + requestBody: + content: + application/json: + schema: + type: object + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + body: + type: string + quotedMsgId: + type: string + example: + phone: "{{testPhone}}" + body: 😀 + quotedMsgId: "{{lastMessageId}}" + operationId: sendReaction + /sendCarousel: + post: + summary: Send Carousel + description: > + You can send product cards via Carousel in two ways: + + + Template messages: do not require a 24-hour customer service window + between you and the recipient. Use sendTemplate. + + + Free-form messages: can be sent only when a customer service window is + open between you and the recipient. Use sendCarousel. + + + The message structure in /sendCarousel is largely similar to sending a + template. However, in this case you must + + explicitly specify all elements that are created in advance when working + with templates. This is because the message + + is sent without using a template. + + + In /sendCarousel, for a Catalog Carousel there can be either 1 URL + button or one or more quick reply buttons. + + + Prefer the simple `cards` array (2–10 cards). Each card needs a header + media/product + + plus a CTA URL or quick-reply buttons. Example: + + + ```json + + { + "phone": "79001234567", + "body": "Pick a product", + "cards": [ + { + "header": { "type": "image", "image": { "link": "https://example.com/1.jpg" } }, + "body": { "text": "Card one" }, + "type": "cta_url", + "action": { "name": "cta_url", "parameters": { "url": "https://example.com/p1", "display_text": "Open" } } + }, + { + "header": { "type": "image", "image": { "link": "https://example.com/2.jpg" } }, + "body": { "text": "Card two" }, + "type": "cta_url", + "action": { "name": "cta_url", "parameters": { "url": "https://example.com/p2", "display_text": "Open" } } + } + ] + } + + ``` + + + `params` with a `CAROUSEL` component is the template-like alternative. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + body: + type: string + description: Text shown above the carousel. Optional. If omitted and params + include a body component, the body will be taken from + params. + cards: + type: array + minItems: 2 + maxItems: 10 + description: Preferred. 2–10 carousel cards (header + body + CTA or quick + replies). + items: + type: object + additionalProperties: true + params: + type: array + items: + type: object + description: > + Required. Template-like structure (same as sendTemplate + params). Must include a CAROUSEL component and its cards. + + + Structure: + + - params[] item with type CAROUSEL and cards (2..10) + + - cards[] item: + - components[] items: + - header: parameters[0] with type image/video/product + - image: {"image": {"link": "https://..."}} + - video: {"video": {"link": "https://..."}} + - product: {"product": {"catalog_id": "...", "product_retailer_id": "..."}} + - button: sub_type url or quick_reply + - url: parameters {"text": "Button", "url": "https://..."} + - quick_reply: parameters[] of {"id": "...", "text": "..."} + quotedMsgId: + type: string + description: Quoted message ID (Cloud API) + chatId: + type: string + description: "Required if phone is not set. Chat ID from the message list. + Examples: 12020721369@c.us or + 120363046942338209@g.us(group)" + phone: + type: integer + description: "Required if chatId is not set. A phone number starting with the + country code. USA example: 12020721369." + application/json: + schema: + type: object + properties: + body: + type: string + description: Text shown above the carousel + cards: + type: array + minItems: 2 + maxItems: 10 + description: Preferred. 2–10 carousel cards. + items: + type: object + additionalProperties: true + params: + type: array + items: + type: object + description: Template-like alternative — include a CAROUSEL component with cards + quotedMsgId: + type: string + chatId: + type: string + phone: + type: integer + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendCarousel + /sendProduct: + post: + summary: Send a Product + description: > + Send a single catalog product or a product list. + + Destination is `chatId` or `phone`. `action` is required: + + - single product: `{ "catalog_id": "...", "product_retailer_id": "..." + }` + + - product list: `{ "catalog_id": "...", "sections": [{ "title": "...", + "product_items": [{ "product_retailer_id": "..." }] }] }` + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - action + properties: + phone: + type: string + description: Recipient phone with country code. Use phone or chatId. + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + body: + type: string + description: Optional message text shown with the product + footer: + type: string + header: + type: string + description: Text header (product list only) + action: + type: object + additionalProperties: true + description: Catalog action (`catalog_id` + `product_retailer_id`, or `sections` + for a list) + additionalProperties: true + example: + chatId: 12020721369@c.us + body: Have a look + action: + catalog_id: "448008021021719" + product_retailer_id: "0001" + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendProduct + /sendTemplate: + post: + summary: Send Template Message + description: > + Send a WhatsApp **template** message (works outside the 24-hour session + window). + + + Use this tool — not `send_message` — when the 24h session is closed. + + + `params` MUST be Cloud API **component objects**, never a flat list of + strings + + and never the old On-Prem `hsm` / `localizable_params` format. + + + Example body variable `{{1}}`: + + + ```json + + { + "type": "body", + "parameters": [{ "type": "text", "text": "Ivan" }] + } + + ``` + + + Do not send `"type": "hsm"` and do not send `params: ["Ivan", "123"]`. + + + Supported `params` button `sub_type` values include: `url`, + `quick_reply`, + + `copy_code` / `coupon_code`, `catalog`, `flow`, `limited_time_offer`, + and + + **`order_details`** (WhatsApp Payments **India only** — requires an + approved + + Utility template with an ORDER_DETAILS button). + + + Convenience wrapper with structured fields: `POST /sendOrderDetails`. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Templates + requestBody: + content: + application/json: + schema: + type: object + properties: + template: + type: string + description: Approved template name (template `name`, not the old HSM + `element_name`) + language: + type: object + description: Template language. Always set `policy` to `deterministic`. + properties: + policy: + type: string + description: Must be `deterministic` + example: deterministic + default: deterministic + code: + type: string + example: en + namespace: + type: string + description: Template namespace from `list_templates` + params: + type: array + description: > + Template components in WhatsApp Cloud API format. + + Each item is an object with `type` (`body`, `header`, + `button`) + + and `parameters` (objects with `type` + `text` / media / + action). + + Never a list of strings. Never HSM `localizable_params`. + items: + type: object + additionalProperties: true + description: | + Component object, e.g. {"type":"body","parameters":[{"type":"text","text":"Ivan"}]} or a header/button/carousel component. Not a string. + phone: + type: string + description: Recipient phone with country code (use phone or chatId) + chatId: + type: string + description: Recipient chat ID (`phone@c.us`, group `@g.us`, or BSUID `@lid`). + Use phone or chatId. + quotedMsgId: + type: string + description: Optional Cloud API wamid to quote + useMMlite: + type: boolean + description: > + Force Marketing Messages API (POST marketing_messages). + + If omitted: auto for MARKETING category when channel has + mm_lite_enabled + + and mm_lite_available service settings. + messageActivitySharing: + type: boolean + description: > + Sets message_activity_sharing on WABA payload. Enables click + tracking webhooks. + + Requires MM Lite path. Ignored on Cloud API fallback. + messageSendTtlSeconds: + type: integer + description: > + Template message TTL in seconds (message_send_ttl_seconds). + + MARKETING via MM Lite: 43200–2592000. AUTHENTICATION: + 30–900. + + UTILITY: 30–43200. AUTH/UTILITY also accept -1 (30-day + custom TTL). + example: + template: test_buttons_2 + language: + policy: deterministic + code: ru + namespace: 41123797_e45e_4f06_a2fa_443b27c6f5ec + phone: "{{testPhone}}" + params: + - type: body + parameters: + - type: text + text: Ivan + operationId: sendTemplate + /messages: + get: + summary: Get messages list + description: | + List stored chat history for this channel (requires history storage). + Filter with `chatId`, `limit`, `last`, message numbers, or time bounds. + parameters: + - $ref: "#/components/parameters/token" + - name: chatId + in: query + schema: + type: string + description: Filter messages for one chat (`phone@c.us`, group `@g.us`, or BSUID + `@lid`) + - name: limit + in: query + schema: + type: integer + description: Max rows to return (default 100) + - name: last + in: query + schema: + type: boolean + description: If true, return the latest messages (DESC). Default false. + - name: lastMessageNumber + in: query + schema: + type: integer + - name: firstMessageNumber + in: query + schema: + type: integer + - name: min_time + in: query + schema: + type: integer + description: Unix timestamp lower bound + - name: max_time + in: query + schema: + type: integer + description: Unix timestamp upper bound + - name: msgId + in: query + schema: + type: string + description: Filter by stored message id + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + notice: + type: string + messages: + type: array + items: + type: object + additionalProperties: true + additionalProperties: true + examples: + ok: + value: + messages: [] + historyDisabled: + value: + notice: saving history disabled + tags: + - Messaging + operationId: listMessages + /readMessage: + post: + summary: Mark message as read + parameters: + - $ref: "#/components/parameters/token" + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + messageId: + type: string + msgId: + type: string + typingIndicator: + type: boolean + default: false + description: Show WhatsApp typing indicator (max 25s or until reply) + application/json: + schema: + type: object + properties: + messageId: + type: string + msgId: + type: string + typingIndicator: + type: boolean + default: false + description: Show WhatsApp typing indicator (max 25s or until reply) + responses: + "200": + description: Server response example + content: + application/json: + schema: + type: object + properties: + result: + type: string + additionalProperties: true + example: + result: success + "401": + description: Invalid token + content: + application/json: + schema: + type: object + properties: + error: + type: string + tags: + - Messaging + operationId: createReadMessage + /uploadMedia: + post: + summary: Upload media + description: > + Upload a file to WhatsApp media storage and get a numeric `mediaId` + + for later use with `send_file` / `send_sticker` (`mediaId` field, not + `body`). + + + Pass the file as `body` **or** `url` — an HTTP(S) URL or a base64 data + URI. + + The `mediaId` in the response is a numeric string (keep it as a string). + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + body: + type: string + description: File HTTP(S) URL or base64 data URI (`data:;base64,...`) + url: + type: string + description: Alias for `body` — public HTTP(S) URL of the file to upload + example: + body: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + mediaId: + type: string + additionalProperties: true + tags: + - Messaging + operationId: createUploadMedia + /sendSticker: + post: + summary: Send sticker message + description: Send a WhatsApp sticker by mediaId or link URL. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + phone: + type: integer + chatId: + type: string + mediaId: + type: string + description: WABA media id from uploadMedia + link: + type: string + description: Public URL to webp sticker + quotedMsgId: + type: string + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendSticker + /sendCtaUrl: + post: + summary: Send CTA URL interactive message + description: Send an interactive message with a single call-to-action URL button. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - body + - displayText + - url + properties: + phone: + type: integer + chatId: + type: string + body: + type: string + displayText: + type: string + description: Button label + url: + type: string + format: uri + header: + type: object + additionalProperties: true + footer: + type: string + quotedMsgId: + type: string + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendCtaUrl + /sendAddressMessage: + post: + summary: Send address request message + description: > + Request shipping address from the user (WhatsApp interactive + `address_message`). + + + **India and Singapore only.** Requires: + + - Business WhatsApp number registered in that country + + - Recipient phone matching the country (`+91` ↔ `IN`, `+65` ↔ `SG`) + + + Pass `country: "IN"` or `country: "SG"`. Eligibility is validated + upstream; + + mismatches (e.g. Singapore phone with `country: "IN"`) return errors + such as + + `Unsupported Interactive Message type` (HTTP 200 with `sent: false`). + + + Optional action parameters: `values`, `saved_addresses`, + `validation_errors`. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - body + properties: + phone: + type: integer + description: Recipient phone (E.164 digits, no +). Must match country. + chatId: + type: string + body: + type: string + description: Body text shown with the address request + country: + type: string + enum: + - IN + - SG + description: Address form country. Defaults to IN if omitted. + example: SG + values: + type: object + description: Optional prefilled address fields + additionalProperties: true + saved_addresses: + type: array + description: Optional previously saved addresses for the user + items: + type: object + additionalProperties: true + validation_errors: + type: object + description: Optional field validation errors when re-prompting + additionalProperties: true + quotedMsgId: + type: string + additionalProperties: true + examples: + singapore: + summary: Singapore + value: + phone: 6531650115 + body: Thanks for your order! Tell us what address you’d like this delivered to. + country: SG + india: + summary: India + value: + phone: 919876543210 + body: Thanks for your order! Tell us what address you’d like this delivered to. + country: IN + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendAddressMessage + /sendOrderDetails: + post: + summary: Send order details (India payments template) + description: > + Send a WhatsApp **order details** payment / invoice message using a + + pre-approved **Utility** template that has an `ORDER_DETAILS` button. + + + **India only** (WhatsApp Payments India). Requires: + + - India WhatsApp Business number + + - Commerce enabled on the channel (`GET`/`POST /commerce`) + + - Approved template with an `ORDER_DETAILS` button + + + Use this method when you need structured fields (`order`, `referenceId`, + + `currency`, `paymentSettings`). The API appends a template button + + `sub_type: order_details` and sends via the same path as `POST + /sendTemplate`. + + + Works **outside the 24-hour session window** (template message). + + + You can also send the same payload yourself with `POST /sendTemplate` by + + including a button component in `params`: + + + ```json + + { + "type": "button", + "sub_type": "order_details", + "index": 0, + "parameters": [{ + "type": "action", + "action": { + "order_details": { + "reference_id": "order-123", + "currency": "INR", + "order": { "status": "pending", "items": [], "subtotal": { "offset": 100, "value": 50000 } } + } + } + }] + } + + ``` + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - template + - namespace + - language + - order + properties: + phone: + type: integer + description: Recipient phone (India E.164 digits, no +). Use phone or chatId. + example: 919876543210 + chatId: + type: string + description: Recipient chatId (e.g. phone@c.us). Use phone or chatId. + template: + type: string + description: Approved Utility template name that includes an ORDER_DETAILS + button + example: order_details_utility + namespace: + type: string + description: Template namespace from the channel / template list + example: your_namespace_uuid + language: + type: object + description: Template language + required: + - code + properties: + code: + type: string + description: Language code + example: en + policy: + type: string + description: Optional language policy + example: deterministic + additionalProperties: true + params: + type: array + description: > + Extra template components (HEADER / BODY / etc.). If an + order_details button is missing, the API appends one from + order / referenceId / currency / paymentSettings. + items: + type: object + additionalProperties: true + referenceId: + type: string + description: Unique order / payment reference id (maps to reference_id) + example: order-123 + currency: + type: string + description: Currency code for India payments + example: INR + paymentSettings: + type: object + description: > + Optional payment settings (UPI / payment gateway / payment + link). Forwarded as payment_settings on the order_details + action. + additionalProperties: true + order: + type: object + description: > + Order payload for the ORDER_DETAILS button. Typical fields: + status, items[], subtotal, tax, shipping, discount. Amount + objects use `{ "offset": 100, "value": }` + (e.g. value 50000 with offset 100 = ₹500.00). + required: + - items + properties: + status: + type: string + description: Order status + example: pending + items: + type: array + description: Line items + items: + type: object + properties: + retailer_id: + type: string + example: SKU-1 + name: + type: string + example: Item + quantity: + type: integer + example: 1 + amount: + type: object + properties: + offset: + type: integer + example: 100 + value: + type: integer + example: 50000 + additionalProperties: true + additionalProperties: true + subtotal: + type: object + properties: + offset: + type: integer + example: 100 + value: + type: integer + example: 50000 + additionalProperties: true + tax: + type: object + additionalProperties: true + shipping: + type: object + additionalProperties: true + discount: + type: object + additionalProperties: true + additionalProperties: true + additionalProperties: true + example: + phone: 919876543210 + template: order_details_utility + namespace: your_namespace_uuid + language: + code: en + referenceId: order-123 + currency: INR + order: + status: pending + items: + - retailer_id: SKU-1 + name: Item + amount: + offset: 100 + value: 50000 + quantity: 1 + subtotal: + offset: 100 + value: 50000 + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendOrderDetails + /sendPaymentRequest: + post: + summary: Send payment request (regional) + description: > + Send a regional payment request interactive message (beta scaffold). + + `region` must be IN, SG, or BR. Payload shape follows Meta regional + payments docs; + + verify on stage before production use. Full regional builders are not + implemented yet. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - phone + - region + properties: + phone: + type: integer + region: + type: string + enum: + - IN + - SG + - BR + body: + type: string + interactive: + type: object + additionalProperties: true + action: + type: object + additionalProperties: true + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/MessageSent" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: sendPaymentRequest + /retrieveMedia: + get: + summary: Retrieve uploaded media metadata + description: | + Get WABA media URL and metadata by mediaId (from uploadMedia). + The returned `url` is temporary and typically expires within ~5 minutes. + parameters: + - $ref: "#/components/parameters/token" + - name: mediaId + in: query + required: true + schema: + type: string + responses: + "200": + description: Media metadata + content: + application/json: + schema: + type: object + properties: + url: + type: string + mimeType: + type: string + sha256: + type: string + fileSize: + type: integer + id: + type: string + additionalProperties: true + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: retrieveMedia + /media/{mediaId}: + delete: + summary: Delete media from WABA storage + description: > + Delete previously uploaded media by numeric `mediaId` (from + `/uploadMedia`). + + + This is the canonical deletion endpoint and uses the REST `DELETE` verb + on the + + media resource path. The older `POST /deleteMedia` is a deprecated + alias. + parameters: + - $ref: "#/components/parameters/token" + - name: mediaId + in: path + required: true + description: Numeric WABA media id + schema: + type: string + responses: + "200": + $ref: "#/components/responses/Success" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: deleteMedia + /deleteMedia: + post: + summary: Delete media from WABA storage (deprecated alias) + deprecated: true + description: > + **Deprecated.** Use `DELETE /media/{mediaId}` instead. + + + This POST alias is kept for backward compatibility with earlier + integrations. + + New integrations should call `DELETE /media/{mediaId}`: 1msg follows + REST + + conventions for resource deletion going forward (delete a resource with + the + + `DELETE` verb on its resource path). + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - mediaId + properties: + mediaId: + type: string + description: Numeric WABA media id + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/Success" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: deleteMediaLegacy + /blockUser: + post: + summary: Block WhatsApp user + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - phone + properties: + phone: + type: integer + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/Success" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Users + operationId: blockUser + /unblockUser: + post: + summary: Unblock WhatsApp user + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - phone + properties: + phone: + type: integer + additionalProperties: true + responses: + "200": + $ref: "#/components/responses/Success" + "400": + $ref: "#/components/responses/BadRequest" + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Users + operationId: unblockUser + /blockedUsers: + get: + summary: List blocked WhatsApp users + description: > + Returns users currently blocked on this WhatsApp channel (WABA `GET + /block_users`). + + Same channel token auth as `blockUser` / `unblockUser`. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Blocked users list + content: + application/json: + schema: + type: object + properties: + blockedUsers: + type: array + items: + type: object + additionalProperties: true + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Users + operationId: listBlockedUsers + /mmLiteStatus: + get: + summary: Get MM Lite availability and status + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: MM Lite status for the channel + content: + application/json: + schema: + type: object + properties: + available: + type: boolean + status: + type: string + message: + type: string + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Messaging + operationId: getMmLiteStatus + /status: + get: + summary: Get channel status + description: > + Return WhatsApp Cloud API connection status for this channel + (`connected` + + when the number can send). May include `accountStatus`, messaging limit, + + and MM Lite availability. + + + Optional `health_status_warning` appears only when Meta Graph health + could + + not be loaded and a soft `connected` response is returned. Omitted on + the + + normal path and when health details are not applicable for the channel — + + never an internal provider/transport name. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Channel status + content: + application/json: + schema: + type: object + properties: + isCloud: + type: boolean + example: true + status: + type: string + description: typically `connected` when the number can send + example: connected + accountStatus: + type: string + example: authenticated + mm_lite_available: + type: boolean + health_status_warning: + type: string + description: Optional soft-fail warning when Meta Graph health_status could not + be loaded. Never includes internal provider names. + additionalProperties: true + example: + isCloud: true + status: connected + accountStatus: authenticated + mm_lite_available: false + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Channel + operationId: getStatus + /settings: + get: + summary: Get channel settings + description: > + Return channel settings: webhook URL(s), delivery flags, and analytics + toggles. + + + Auto-disable / circuit state matches `GET /webhook`. **Prefer + `webhookStatuses`** + + (one row per configured URL). The breaker is per URL, not per channel. + + + Channel-level `haveDisabledWebhooks` is `true` when **at least one** URL + in + + `webhookUrl` is sticky auto-disabled — not "the channel is dead". Live + URLs + + still receive events. Top-level `circuitState` / `reason` / `fails` / + `trips` + + are a compatibility summary of one URL (first sticky-disabled, else + first + + configured). + + + This is the same `GET /settings` endpoint as the REST API (previously + missing from MCP). + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Current settings + content: + application/json: + schema: + type: object + properties: + webhookUrl: + oneOf: + - type: string + - type: array + items: + type: string + description: One URL, or several if multiple webhooks are configured + guaranteedHooks: + type: boolean + description: Retry webhooks until acknowledged + ackNotificationsOn: + type: boolean + description: Include message ACK / status events in webhooks + rawHooks: + type: boolean + description: Forward raw provider webhook payloads + mm_lite_enabled: + type: boolean + template_analytics_enabled: + type: boolean + cta_url_link_tracking_opted_out: + type: boolean + haveDisabledWebhooks: + type: boolean + description: > + `true` when at least one URL in `webhookUrl` is sticky + auto-disabled. + + Not "the channel is dead": other configured URLs still + receive events. + circuitState: + type: string + description: > + Compatibility scalar for **one** URL (first + sticky-disabled, else first + + configured). Prefer `webhookStatuses[].circuitState`. + enum: + - ok + - degraded + - open + - half_open + - disabled + reason: + type: string + description: Last qualifying fail reason of the summary URL + fails: + type: integer + description: > + Diagnostic only (summary URL). Qualifying failures in the + rolling + + ~10 minute breaker window — not lifetime. Prefer + `webhookStatuses`. + trips: + type: integer + description: > + Diagnostic only (summary URL). Failed recovery probes (≈15 + min → + + 1 h → 6 h). Sticky disable after 3. Not a blind unblock + timer. + disabledAt: + type: integer + description: Epoch milliseconds when the summary URL became sticky-disabled + firstFailAt: + type: integer + description: > + Diagnostic only (summary URL). Epoch ms of the first fail + in the + + current ~10 minute window (pairs with `fails`). + lastStatus: + type: integer + description: Last HTTP status from the summary URL, when known + nextProbeAt: + type: integer + description: Epoch milliseconds of the next half-open probe for the summary URL, + if any + disabledWebhooks: + type: array + description: Currently configured URLs that are sticky auto-disabled (subset of + `webhookUrl`) + items: + type: object + additionalProperties: true + webhookStatuses: + type: array + description: One entry per currently configured URL. Prefer this over top-level + `haveDisabledWebhooks` / `circuitState`. + items: + $ref: "#/components/schemas/WebhookUrlStatus" + additionalProperties: true + example: + webhookUrl: https://example.com/webhook + guaranteedHooks: false + ackNotificationsOn: true + rawHooks: false + haveDisabledWebhooks: false + circuitState: ok + disabledWebhooks: [] + webhookStatuses: + - url: https://example.com/webhook + circuitState: ok + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Channel + operationId: listSettings + post: + summary: Update channel settings + description: > + Update channel settings. Only send fields you want to change. + + + `webhookUrl` **replaces** the stored list (one URL string, or up to 5 + URLs as an array). + + Passing an empty value clears webhooks. Repeating the same URL(s) also + clears a + + sticky auto-disable. With several URLs, send the complete array to + re-enable one + + of them — omitting a URL removes it from the channel. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + webhookUrl: + oneOf: + - type: string + - type: array + items: + type: string + description: Replacement webhook URL, or array of URLs (max 5) + guaranteedHooks: + type: boolean + ackNotificationsOn: + type: boolean + rawHooks: + type: boolean + template_analytics_enabled: + type: boolean + cta_url_link_tracking_opted_out: + type: boolean + additionalProperties: true + example: + webhookUrl: https://example.com/webhook + ackNotificationsOn: true + responses: + "200": + description: Updated settings + content: + application/json: + schema: + type: object + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Channel + operationId: createSettings + /commerce: + get: + summary: Get Commerce Settings + description: > + Returns catalog/cart commerce settings for the channel. + + + Fails with a provider error when the WABA has no catalog linked — that + is an + + API/account limitation, not an MCP schema bug. + + + - `is_catalog_visible` — show catalog storefront icon (`true`) or hide + it (`false`). + + - `is_cart_enabled` — enable cart (`true`) or disable it (`false`). + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Commerce settings + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + description: Catalog id + is_cart_enabled: + type: boolean + description: Whether the cart is enabled + is_catalog_visible: + type: boolean + description: Whether the catalog storefront icon is shown + additionalProperties: true + example: + - id: "789887292550821" + is_cart_enabled: true + is_catalog_visible: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Catalog + operationId: getCommerce + post: + summary: Set Commerce Settings + description: > + Update catalog/cart commerce settings via the `params` object. + + + - `params.is_catalog_visible` — show catalog storefront icon (`true`) or + hide it (`false`). + + - `params.is_cart_enabled` — enable cart (`true`) or disable it + (`false`). + + + Blocked when the channel subscription limit is exceeded. + + Requires a commerce-capable channel (Cloud Functions `/commerceWAV2`). + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - params + properties: + params: + type: object + required: + - is_cart_enabled + - is_catalog_visible + properties: + is_cart_enabled: + type: boolean + description: Enable cart + is_catalog_visible: + type: boolean + description: Show catalog storefront icon + additionalProperties: true + additionalProperties: true + example: + params: + is_cart_enabled: true + is_catalog_visible: true + responses: + "200": + description: Commerce updated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + additionalProperties: true + example: + success: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Catalog + operationId: createCommerce + /conversationalAutomation: + get: + summary: Get conversational automation settings + description: > + Get WhatsApp conversational components for the channel (welcome message, + + ice-breaker prompts, and slash commands). + + + Proxies Meta/360dialog `GET /conversational_automation`. + + + When `enable_welcome_message` is true and a user opens chat for the + first + + time, Meta delivers a webhook message with `type: request_welcome`. The + + inbound formatter exposes that as `type: "request_welcome"` and + + `meta.request_welcome: true` so your webhook can send a custom welcome + reply. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Conversational automation settings + content: + application/json: + schema: + $ref: "#/components/schemas/ConversationalAutomation" + example: + enable_welcome_message: true + prompts: + - How can I help? + commands: + - command_name: help + command_description: Get support options + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Channel + operationId: getConversationalAutomation + post: + summary: Set conversational automation settings + description: | + Update WhatsApp conversational components. + + Allowed body fields (others are ignored): + - `enable_welcome_message` (boolean) + - `prompts` (string[], max 4, each ≤ 80 chars) + - `commands` (`{ command_name, command_description }[]`) + + Proxies Meta/360dialog `POST /conversational_automation`. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ConversationalAutomation" + example: + enable_welcome_message: true + prompts: + - How can I help? + commands: + - command_name: help + command_description: Get support options + responses: + "200": + description: > + Updated settings from WABA, or legacy response.error wrapper on + upstream failure. + content: + application/json: + schema: + type: object + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Channel + operationId: setConversationalAutomation + /webhook: + get: + summary: Get webhook URL + description: > + Return the webhook URL(s) currently configured for this channel, plus + delivery + + status for each URL. + + + `webhookUrl` is a string when a single URL is set, an array of strings + when + + multiple URLs are configured, or `null` if none is set. + + + **Prefer `webhookStatuses`.** The circuit breaker is per URL, not per + channel. + + If 1 of 4 URLs is sticky-disabled, that URL is skipped; the other three + still + + receive events. Send/receive are not affected. + + + Channel-level `haveDisabledWebhooks`, `circuitState`, `reason`, `fails`, + + `trips`, and timestamps are a compatibility summary of **one** URL (the + first + + sticky-disabled URL, else the first configured URL). They are not "the + channel + + is dead". + + + - `haveDisabledWebhooks` — `true` when **at least one** URL in + `webhookUrl` is + sticky auto-disabled. Live URLs still get events. + - `circuitState` — compressed scalar for that same primary URL: + `ok` | `degraded` | `open` | `half_open` | `disabled`. + - `disabledWebhooks` — currently configured URLs that are + sticky-disabled + (subset of `webhookUrl`). + - `webhookStatuses` — one row per currently configured URL. Use this + array + to see which endpoints are live vs skipped. + - `fails` / `trips` / `firstFailAt` — **diagnostics for support**, not + product + UI. `fails` = failures in a rolling ~10 minute window (not lifetime). + `trips` = failed recovery probes on the 15 min → 1 h → 6 h schedule (sticky + disable after 3). Clients can ignore these and use `webhookStatuses` + + `disabledWebhooks` only. + + Sticky disable skips delivery; it does not unconfigure the URL (it stays + in + + `webhookUrl`). Re-enable with `POST /webhook` or `POST /settings`. Those + + endpoints **replace** the whole list — with multiple URLs, send the full + array. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Current webhook URL and per-URL circuit status + content: + application/json: + schema: + type: object + properties: + webhookUrl: + oneOf: + - type: string + format: uri + - type: array + items: + type: string + format: uri + - type: "null" + description: Configured webhook URL, array of URLs, or null when none is set + haveDisabledWebhooks: + type: boolean + description: > + `true` when at least one URL in `webhookUrl` is sticky + auto-disabled. + + Not "the channel is dead": other configured URLs still + receive events. + + Send/receive are unaffected. + circuitState: + type: string + description: > + Compatibility scalar for **one** URL (first + sticky-disabled, else first + + configured). Not the channel as a whole. Prefer + `webhookStatuses[].circuitState`. + enum: + - ok + - degraded + - open + - half_open + - disabled + reason: + type: string + description: Last qualifying fail reason of the summary URL (same URL as + `circuitState`) + fails: + type: integer + description: > + Diagnostic only (summary URL). Qualifying failures in the + rolling + + ~10 minute breaker window — not lifetime and not customer + retries. + + Prefer `webhookStatuses` / `disabledWebhooks`. + trips: + type: integer + description: > + Diagnostic only (summary URL). Failed recovery probes (≈15 + min → + + 1 h → 6 h). Sticky disable after 3. Not a blind unblock + timer. + disabledAt: + type: integer + description: Epoch milliseconds when the summary URL became sticky-disabled + firstFailAt: + type: integer + description: > + Diagnostic only (summary URL). Epoch ms of the first fail + in the + + current ~10 minute window (pairs with `fails`). + lastStatus: + type: integer + description: Last HTTP status from the summary URL, when known + nextProbeAt: + type: integer + description: Epoch milliseconds of the next half-open probe for the summary URL, + if any + disabledWebhooks: + type: array + description: > + Currently configured URLs that are sticky auto-disabled + (subset of `webhookUrl`). + + Does not include leftover URLs that are no longer + configured. + items: + type: object + additionalProperties: true + webhookStatuses: + type: array + description: > + One entry per currently configured URL. Prefer this over + top-level + + `haveDisabledWebhooks` / `circuitState` when more than one + webhook is set. + items: + $ref: "#/components/schemas/WebhookUrlStatus" + additionalProperties: true + examples: + healthy: + summary: Single URL delivering + value: + webhookUrl: https://example.com/webhook + haveDisabledWebhooks: false + circuitState: ok + disabledWebhooks: [] + webhookStatuses: + - url: https://example.com/webhook + circuitState: ok + mixed: + summary: One of several URLs sticky-disabled + value: + webhookUrl: + - https://live.example.com/webhook + - https://down.example.com/webhook + haveDisabledWebhooks: true + circuitState: disabled + reason: http_404 + fails: 1 + trips: 3 + disabledWebhooks: + - url: https://down.example.com/webhook + reason: http_404 + state: disabled + fails: 1 + trips: 3 + webhookStatuses: + - url: https://live.example.com/webhook + circuitState: ok + - url: https://down.example.com/webhook + circuitState: disabled + reason: http_404 + fails: 1 + trips: 3 + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Webhooks + operationId: getWebhook + post: + summary: Set webhook URL + description: > + Set the client webhook URL that receives inbound events for this + channel. + + + **Replaces** the stored webhook list (it does not append). To deliver + the same + + events to several endpoints, pass an array in `webhookUrl` (max 5) or + use + + `POST /settings`. With several URLs already configured, posting only the + + disabled URL **drops the others** — send the complete array to re-enable + one + + of many. + + + Incoming payloads include messages, delivery ACKs, group updates, + coexistence + + echoes, and calling events. WhatsApp Calling payloads (`type: "calls"`) + are + + documented under the **Calling** tag. Call permission replies arrive on + the + + normal messages path (`call_permission_reply`). + + + Repeating `POST /webhook` with the same URL(s) clears an auto-disable + (self-serve + + re-enable). Send/receive are not affected by webhook auto-disable. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - webhookUrl + properties: + webhookUrl: + oneOf: + - type: string + format: uri + - type: array + items: + type: string + format: uri + maxItems: 5 + description: > + HTTP or HTTPS URL, or array of URLs (max 5). Replaces the + stored list. + + Empty values are rejected — clear webhooks with `POST + /settings`. + additionalProperties: true + examples: + single: + summary: Single URL + value: + webhookUrl: https://example.com/webhook + multiple: + summary: Several URLs (replaces the list) + value: + webhookUrl: + - https://example.com/webhook + - https://backup.example.com/webhook + responses: + "200": + description: Webhook configured + content: + application/json: + schema: + type: object + properties: + set: + type: boolean + description: True when the stored webhook URL(s) match the request + webhookUrl: + oneOf: + - type: string + - type: array + items: + type: string + description: Currently stored webhook URL or list + additionalProperties: true + example: + set: true + webhookUrl: https://example.com/webhook + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Webhooks + operationId: setWebhook + /callingSettings: + get: + summary: Get calling settings + description: > + Return WhatsApp Calling API settings for this channel (beta). + + + Proxies upstream `GET /calling/settings`. + + + **Prerequisites** + + - Number must be eligible for Meta Calling (Cloud API; not COEX) + + - Trial / `subscriptionBlocked` channels receive **403** plain text + + - You need your own WebRTC or SIP stack; 1msg is a **signaling proxy** + only + and does **not** store call history or recordings + + See the **Calling** tag overview for inbound/outbound flows and + webhooks. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Calling settings (and possibly other Cloud API settings Meta returns) + content: + application/json: + schema: + $ref: "#/components/schemas/CallingSettings" + example: + calling: + status: ENABLED + call_icon_visibility: DEFAULT + callback_permission_status: ENABLED + sip: + status: DISABLED + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Calling + operationId: getCallingSettings + post: + summary: Update calling settings + description: > + Enable, disable, or update WhatsApp Calling settings (beta). + + + Proxies upstream `POST /calling/settings`. + + Body is forwarded as-is (1msg does not validate fields). + + + **Common fields under `calling`** + + - `status` (`ENABLED` | `DISABLED`) — required to turn calling on/off + + - `call_icon_visibility` (`DEFAULT` | `DISABLE_ALL`) — optional + + - `callback_permission_status` (`ENABLED` | `DISABLED`) — optional; + when enabled, inbound user calls grant callback permission + - `call_hours` — optional hours / timezone object + + - `sip` — optional SIP trunk; when SIP is ENABLED, Graph call actions + and + calling webhooks are not used + - `srtp_key_exchange_protocol` (`DTLS` | `SDES`) — SDES only with SIP + + - `video.status` — optional + + + Meta may accept only one feature group per request — prefer focused + updates + + (e.g. enable status first, then SIP). + + + Trial / `subscriptionBlocked` → **403** plain text. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CallingSettings" + examples: + enable: + summary: Enable calling + value: + calling: + status: ENABLED + call_icon_visibility: DEFAULT + callback_permission_status: ENABLED + disable: + summary: Disable calling + value: + calling: + status: DISABLED + enableSip: + summary: Enable SIP (disables Graph call webhooks) + value: + calling: + status: ENABLED + sip: + status: ENABLED + servers: + - hostname: sip.example.com + port: 5061 + responses: + "200": + description: | + Usually `{ "success": true }` from upstream, or legacy + `{ "result": "success" }` / `{ "response": { "error": "..." } }`. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + result: + type: string + example: success + response: + type: object + properties: + error: + type: string + additionalProperties: true + additionalProperties: true + example: + success: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Calling + operationId: updateCallingSettings + /initiateCall: + post: + summary: Call action (connect / pre_accept / accept / reject / terminate) + description: > + Perform a WhatsApp Calling action (beta). + + + Proxies upstream `POST /calling/calls`. Despite the historical path + + name `/initiateCall`, this endpoint handles **all** call actions: + + + | action | Use | Required | + + |--------|-----|----------| + + | `connect` | Outbound business → user | `to` + `session` (`sdp_type: + offer`) | + + | `pre_accept` | Inbound (optional, reduces audio clipping) | `call_id` + + `session` (`sdp_type: answer`) | + + | `accept` | Inbound answer | `call_id` + `session` (`sdp_type: answer`) + | + + | `reject` | Decline inbound | `call_id` | + + | `terminate` | Hang up | `call_id` | + + + **SDP / media (critical)** + + - `accept` / `pre_accept` require a **WebRTC-generated SDP answer**. + + - Do **not** send Meta's offer SDP back as the answer. + + - Postman (or curl) alone **cannot** establish real media — you need a + WebRTC or SIP stack. 1msg only proxies signaling. + + Answer within ~**30–60 seconds** of an inbound `connect` webhook or Meta + + terminates as unanswered. Common Meta errors include Calling not enabled + + (`138000`), no permission (`138006`), SDP validation failures. + + + **Outbound** requires a prior Call Permission Request (CPR) acceptance. + + See the **Calling** tag overview for the full outbound flow and CPR + limits. + + + Trial / `subscriptionBlocked` → **403** plain text. + + Upstream failures often return HTTP 200 with `{ "response": { "error": + "" } }`. + + `Invalid API KEY` is used only when Meta/360 body actually indicates an + + invalid API key or token. Other upstream 401s (notably call permission + + `138006`) pass through `error.message` / `error_user_msg`. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/InitiateCallRequest" + examples: + outboundConnect: + summary: Outbound connect (business SDP offer) + value: + messaging_product: whatsapp + to: "12185552828" + action: connect + biz_opaque_callback_data: order-123 + session: + sdp_type: offer + sdp: "[REPLACE_WITH_WEBRTC_SDP]" + preAccept: + summary: Inbound pre_accept (WebRTC answer SDP) + value: + messaging_product: whatsapp + call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh + action: pre_accept + session: + sdp_type: answer + sdp: "[REPLACE_WITH_WEBRTC_SDP]" + accept: + summary: Inbound accept (WebRTC answer SDP) + value: + messaging_product: whatsapp + call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh + action: accept + session: + sdp_type: answer + sdp: "[REPLACE_WITH_WEBRTC_SDP]" + reject: + summary: Reject inbound call + value: + messaging_product: whatsapp + call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh + action: reject + terminate: + summary: Terminate active call + value: + messaging_product: whatsapp + call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh + action: terminate + responses: + "200": + description: Call action result from upstream, or legacy error wrapper + content: + application/json: + schema: + $ref: "#/components/schemas/InitiateCallResponse" + examples: + success: + summary: Accept / pre_accept / reject / terminate success + value: + messaging_product: whatsapp + success: true + connectSuccess: + summary: Outbound connect success (includes call id) + value: + messaging_product: whatsapp + calls: + - id: wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA + upstreamError: + summary: Upstream error wrapped by 1msg + value: + response: + error: Calling not enabled + callPermissionDenied: + summary: Meta 138006 (upstream 401, not Invalid API KEY) + value: + response: + error: No approved call permission from the recipient + invalidApiKey: + summary: Real invalid D360/Meta token + value: + response: + error: Invalid API KEY + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Calling + operationId: initiateCall + /groups: + post: + summary: Create Group + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - groupName + properties: + groupName: + type: string + description: Group subject / name + description: + type: string + description: Optional group description + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + tags: + - Groups + operationId: createGroups + get: + summary: Get Groups List + description: List WhatsApp groups for this channel. Paginate with `limit`, + `before`, and `after`. + parameters: + - $ref: "#/components/parameters/token" + - name: limit + in: query + schema: + type: integer + description: Max groups to return + - name: before + in: query + schema: + type: string + description: Cursor for the previous page + - name: after + in: query + schema: + type: string + description: Cursor for the next page + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Groups + operationId: listGroups + /groups/{groupId}: + get: + summary: Get Group Info + parameters: + - $ref: "#/components/parameters/token" + - name: fields + in: query + schema: + type: string + description: Comma-separated group fields to return + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Groups + operationId: getGroupsGroupId + parameters: + - name: groupId + in: path + required: true + schema: + type: string + example: "{{createdGroupId}}" + post: + summary: Update Group Info + description: | + Update group subject, description, and/or profile picture. + Path `groupId` is the WABA group id (without `@g.us`). + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + subject: + type: string + description: New group subject / name + description: + type: string + description: New group description + profile_picture_file: + type: string + description: Image URL or base64 data URI for the group profile picture + example: + subject: Support team + description: Customer support + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Groups + operationId: createGroupsGroupId + delete: + summary: Delete Group + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + response: + type: object + additionalProperties: true + additionalProperties: true + tags: + - Groups + operationId: deleteGroupsGroupId + /groups/{groupId}/inviteLink: + get: + summary: Get Invite Link + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Groups + operationId: getGroupsGroupIdInvitelink + parameters: + - name: groupId + in: path + required: true + schema: + type: string + example: "{{createdGroupId}}" + post: + summary: Reset Invite Link + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Groups + operationId: createGroupsGroupIdInvitelink + /whatsapp_business_encryption: + get: + summary: Get business encryption public key + description: > + Retrieve the WhatsApp business public key and signature status for this + channel's + + phone number. Required before publishing or sending Flows that use data + encryption. + parameters: + - $ref: "#/components/parameters/token" + responses: + "200": + description: Business encryption key status + content: + application/json: + schema: + type: object + properties: + business_public_key: + type: string + description: Stored 2048-bit RSA public key (PEM) + business_public_key_signature_status: + type: string + enum: + - VALID + - MISMATCH + data: + type: array + items: + type: object + additionalProperties: true + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Flows + operationId: getWhatsappBusinessEncryption + post: + summary: Set business encryption public key + description: > + Upload and sign a 2048-bit RSA business public key (PEM) for this + channel's phone number. + + Meta requires a signed key before Flow publish/send. Only one active key + per number; + + a new upload replaces the previous key. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - business_public_key + properties: + business_public_key: + type: string + description: 2048-bit RSA public key in PEM format + example: | + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... + -----END PUBLIC KEY----- + responses: + "200": + description: Public key uploaded and signed + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + additionalProperties: true + "400": + description: Missing or invalid PEM key + content: + application/json: + schema: + type: object + properties: + error: + type: string + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Flows + operationId: setWhatsappBusinessEncryption + /flows: + post: + summary: Create Flow + description: > + Create a WhatsApp Flow (`name` + `categories` required). + + Currently returns HTTP 501 until the Meta Graph Flows rewrite is + available. + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - categories + properties: + name: + type: string + description: Flow name + categories: + type: array + items: + type: string + enum: + - SIGN_UP + - SIGN_IN + - APPOINTMENT_BOOKING + - LEAD_GENERATION + - CONTACT_US + - CUSTOMER_SUPPORT + - SURVEY + - OTHER + description: One or more Flow categories + endpointUri: + type: string + description: HTTPS endpoint for the Flow data channel + publish: + type: boolean + description: Publish immediately after create + flowJson: + type: object + additionalProperties: true + description: Optional Flow JSON document + example: + name: lead_form + categories: + - LEAD_GENERATION + publish: false + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + "501": + description: WhatsApp Flows are not available on this channel yet + tags: + - Flows + operationId: createFlows + get: + summary: List Flows + description: > + List WhatsApp Flows for the WABA. + + Currently returns HTTP 501 until the Meta Graph Flows rewrite is + available. + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + - name: fields + in: query + schema: + type: string + description: Comma-separated Flow fields to return + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + type: object + additionalProperties: true + paging: + type: object + additionalProperties: true + count: + type: integer + total: + type: integer + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + "501": + description: WhatsApp Flows are not available on this channel yet + tags: + - Flows + operationId: listFlows + /flows/{flowId}: + get: + summary: Get Flow Details + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + tags: + - Flows + operationId: getFlowsFlowId + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + delete: + summary: Delete Flow + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + tags: + - Flows + operationId: deleteFlowsFlowId + /flows/{flowId}/metadata: + patch: + summary: Update Flow Metadata + description: > + Update Flow `name`, `categories`, and/or `endpointUri`. + + Currently returns HTTP 501 until the Meta Graph Flows rewrite is + available. + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + categories: + type: array + items: + type: string + enum: + - SIGN_UP + - SIGN_IN + - APPOINTMENT_BOOKING + - LEAD_GENERATION + - CONTACT_US + - CUSTOMER_SUPPORT + - SURVEY + - OTHER + endpointUri: + type: string + description: HTTPS endpoint for the Flow data channel + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + "501": + description: WhatsApp Flows are not available on this channel yet + tags: + - Flows + operationId: patchFlowsFlowIdMetadata + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + /flows/{flowId}/assets: + patch: + summary: Update Flow Structure + description: > + Replace the Flow JSON document (`flowJson`). + + Currently returns HTTP 501 until the Meta Graph Flows rewrite is + available. + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - flowJson + properties: + flowJson: + type: object + additionalProperties: true + description: WhatsApp Flow JSON document + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + validationErrors: + type: array + items: + type: object + additionalProperties: true + error: + description: Error details returned by the provider. May be a string or a JSON + object. + additionalProperties: true + "501": + description: WhatsApp Flows are not available on this channel yet + tags: + - Flows + operationId: patchFlowsFlowIdAssets + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + /flows/{flowId}/preview: + get: + summary: Preview Flow + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Flows + operationId: getFlowsFlowIdPreview + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + /flows/{flowId}/publish: + post: + summary: Publish Flow + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Flows + operationId: createFlowsFlowIdPublish + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + /flows/{flowId}/deprecate: + post: + summary: Deprecate Flow + parameters: + - $ref: "#/components/parameters/token" + - name: wabaAccountId + in: query + schema: + type: string + example: "{{wabaAccountId}}" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - Flows + operationId: createFlowsFlowIdDeprecate + parameters: + - $ref: "#/components/parameters/flowId" + example: "{{flowId}}" + /templates: + get: + summary: Get templates list + description: List message templates. Paginate with `limit` / `offset`; sort by + `id`, `name`, or `status`. + parameters: + - $ref: "#/components/parameters/token" + - name: limit + in: query + schema: + type: integer + - name: offset + in: query + schema: + type: integer + - name: sort + in: query + schema: + type: string + enum: + - id + - name + - status + description: Sort field (`id`, `name`, or `status`) + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + total: + type: integer + templates: + type: array + items: + type: object + additionalProperties: true + error: + type: object + additionalProperties: true + additionalProperties: true + tags: + - Templates + operationId: listTemplates + /addTemplate: + post: + summary: Create message template + description: > + Create a WABA message template (`name`, `category`, `language`, + `components`). + + After create, Meta reviews the template; list it with `GET /templates`. + parameters: + - $ref: "#/components/parameters/token" + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Template name + example: hello_world + category: + type: string + description: MARKETING, UTILITY, or AUTHENTICATION + example: UTILITY + language: + type: string + description: Template language code (e.g. en_US) + example: en_US + components: + type: array + items: + type: object + additionalProperties: true + description: Template components (HEADER, BODY, FOOTER, BUTTONS, CAROUSEL) + additionalProperties: true + example: + name: hello_world + category: UTILITY + language: en_US + components: + - type: BODY + text: Hello {{1}} + responses: + "200": + description: Template created. Provider payload is wrapped in `response`. + content: + application/json: + schema: + type: object + properties: + response: + type: object + description: Upstream create-template payload + additionalProperties: true + additionalProperties: true + example: + response: + id: "123456789" + status: PENDING + category: MARKETING + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Templates + operationId: addTemplate + /removeTemplate: + post: + summary: Remove message template + description: Delete a message template by `name` (all language versions of that name). + parameters: + - $ref: "#/components/parameters/token" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + properties: + name: + type: string + description: Template name to delete + example: + name: hello_world + responses: + "200": + description: Template removed + content: + application/json: + schema: + type: object + additionalProperties: true + "401": + $ref: "#/components/responses/InvalidToken" + "500": + $ref: "#/components/responses/InternalError" + tags: + - Templates + operationId: removeTemplate +components: + parameters: + flowId: + name: flowId + in: path + required: true + schema: + type: string + description: Flow ID + token: + name: token + in: query + required: true + schema: + type: string + description: JWT token or API key for authorization + date: + name: date + in: query + required: false + schema: + type: string + format: date + description: Filter by date (YYYY-MM-DD) + groupId: + name: groupId + in: path + required: true + schema: + type: string + description: Group ID (phone number with country code) + schemas: + ErrorResponse: + type: object + properties: + error: + type: string + description: Error message + description: Standard error response + MessageSentResponse: + type: object + properties: + sent: + type: boolean + description: Whether the message was successfully queued for sending + id: + type: string + description: Message ID + message: + type: string + description: Status message + description: + type: string + description: Detailed description + additionalProperties: true + description: Response for successfully sent message + SuccessResponse: + type: object + properties: + result: + type: string + description: Operation result + additionalProperties: true + description: Generic success response + ProfileInfo: + type: object + properties: + about: + type: string + description: Profile's About section + address: + type: string + description: Address of the business + description: + type: string + description: Description of the business + email: + type: string + description: Business email + phone: + type: string + description: Linked phone number + vertical: + type: string + enum: + - Automotive + - Beauty, Spa and Salon + - Clothing and Apparel + - Education + - Entertainment + - Event Planning and Service + - Finance and Banking + - Food and Grocery + - Public Service + - Hotel and Lodging + - Medical and Health + - Non-profit + - Professional Services + - Shopping and Retail + - Travel and Transportation + - Restaurant + - Other + description: Industry of the business + photo: + type: string + description: Profile photo URL + websites: + type: array + items: + type: string + additionalProperties: true + description: WhatsApp Business profile information + ConversationalAutomation: + type: object + properties: + enable_welcome_message: + type: boolean + description: Enable the automatic welcome message for new conversations + prompts: + type: array + maxItems: 4 + description: Ice-breaker prompt strings (max 4, each ≤ 80 characters) + items: + type: string + maxLength: 80 + commands: + type: array + maxItems: 30 + description: Slash commands shown in WhatsApp + items: + type: object + required: + - command_name + - command_description + properties: + command_name: + type: string + maxLength: 32 + command_description: + type: string + maxLength: 256 + additionalProperties: true + additionalProperties: true + CallingSettings: + type: object + description: > + Calling settings payload for GET/POST `/callingSettings`. + + Proxies upstream `GET|POST /calling/settings`. + + Extra Meta fields may appear on GET responses; document core fields + below. + properties: + calling: + type: object + description: Calling feature configuration for the business phone number + properties: + status: + type: string + description: Enable or disable Calling API on this number + enum: + - ENABLED + - DISABLED + example: ENABLED + call_icon_visibility: + type: string + description: Controls call icon visibility in the WhatsApp client + enum: + - DEFAULT + - DISABLE_ALL + example: DEFAULT + callback_permission_status: + type: string + description: > + When ENABLED, a user who calls your business automatically + grants + + call permission for business-initiated callbacks (subject to + Meta rules). + enum: + - ENABLED + - DISABLED + example: ENABLED + srtp_key_exchange_protocol: + type: string + description: | + SRTP key exchange. DTLS is default/recommended. + SDES is only valid when SIP signaling is enabled. + enum: + - DTLS + - SDES + example: DTLS + call_hours: + type: object + description: Optional call hours / timezone configuration (Meta shape) + additionalProperties: true + properties: + status: + type: string + example: ENABLED + timezone: + type: string + example: America/Los_Angeles + day_of_week_start: + type: string + example: MONDAY + sip: + type: object + description: > + SIP trunk settings. When SIP is ENABLED, Graph call actions and + + calling webhooks are not used — Meta dials your SIP server + directly. + properties: + status: + type: string + enum: + - ENABLED + - DISABLED + example: DISABLED + servers: + type: array + items: + type: object + properties: + hostname: + type: string + example: sip.example.com + port: + type: integer + example: 5061 + request_uri_user_params: + type: object + additionalProperties: + type: string + sip_user_password: + type: string + description: Present on GET when SIP credentials are returned by Meta + password: + type: string + description: Alternate password field name from some Meta responses + app_id: + type: string + additionalProperties: true + additionalProperties: true + video: + type: object + description: Video calling toggle when supported + properties: + status: + type: string + enum: + - ENABLED + - DISABLED + additionalProperties: true + audio: + type: object + description: Audio settings (typically response-only) + properties: + status: + type: string + additionalProperties: true + restrictions: + type: object + description: Calling restrictions (response-only) + additionalProperties: true + ip_addresses: + type: object + description: Meta media IP ranges (response-only) + additionalProperties: true + call_icons: + type: object + description: Call icon country restrictions (response-only) + additionalProperties: true + additionalProperties: true + additionalProperties: true + InitiateCallRequest: + type: object + description: > + Call action payload for `POST /initiateCall` (proxies upstream `POST + /calling/calls`). + + + Despite the path name, this endpoint handles **all** call actions — not + only + + outbound connect. + + + ## Required fields by `action` + + + | action | Required | `session` | + + |--------|----------|-----------| + + | `connect` (outbound) | `messaging_product`, `to`, `action` | + `sdp_type: offer` + business WebRTC SDP | + + | `pre_accept` | `messaging_product`, `call_id`, `action` | `sdp_type: + answer` (WebRTC-generated) | + + | `accept` | `messaging_product`, `call_id`, `action` | `sdp_type: + answer` (WebRTC-generated) | + + | `reject` | `messaging_product`, `call_id`, `action` | none | + + | `terminate` | `messaging_product`, `call_id`, `action` | none | + + + **Critical:** For `pre_accept` / `accept`, `session.sdp` must be a + + **WebRTC-generated SDP answer**. Do not echo Meta's offer SDP back. + + Postman alone cannot establish real media — you need a WebRTC (or SIP) + stack. + required: + - messaging_product + - action + properties: + messaging_product: + type: string + description: Must be `whatsapp` + enum: + - whatsapp + example: whatsapp + action: + type: string + description: Call control action + enum: + - connect + - pre_accept + - accept + - reject + - terminate + example: connect + call_id: + type: string + description: > + WhatsApp call id from the inbound/outbound calls webhook + (`calls[].id`). + + Required for `pre_accept`, `accept`, `reject`, `terminate`. + example: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh + to: + type: string + description: | + Recipient WhatsApp user phone (digits, country code, no +). + Required for outbound `connect`. + example: "12185552828" + biz_opaque_callback_data: + type: string + description: Optional opaque string echoed on later call webhooks for correlation + maxLength: 512 + example: order-123-callback + session: + type: object + description: WebRTC SDP session (required for connect / pre_accept / accept) + required: + - sdp_type + - sdp + properties: + sdp_type: + type: string + description: offer for outbound connect; answer for pre_accept/accept + enum: + - offer + - answer + example: offer + sdp: + type: string + description: > + Full SDP (RFC 8866). Replace placeholders with SDP from your + WebRTC stack. + + Must negotiate ICE, DTLS-SRTP, and OPUS for WhatsApp media. + example: "[REPLACE_WITH_WEBRTC_SDP]" + additionalProperties: true + additionalProperties: true + InitiateCallResponse: + type: object + description: > + Successful call action response from upstream, returned as-is. + + On empty upstream body, 1msg may return `{ "result": "success" }`. + + Upstream failures are often wrapped as HTTP 200 `{ "response": { + "error": "..." } }`. + properties: + messaging_product: + type: string + example: whatsapp + success: + type: boolean + example: true + calls: + type: array + description: Present on outbound `connect` — contains the new call id + items: + type: object + properties: + id: + type: string + example: wacid.HBgLMTIxODU1NTI4MjgVAgARGCAyODRQIAFRoA + additionalProperties: true + result: + type: string + description: Legacy success marker when upstream returns an empty body + example: success + response: + type: object + description: Present when 1msg wraps an upstream error + properties: + error: + type: string + additionalProperties: true + additionalProperties: true + WebhookUrlStatus: + type: object + description: | + Circuit / auto-disable status for one configured webhook URL. + The breaker is per URL (`instanceId` + URL hash), not per channel. + required: + - url + - circuitState + properties: + url: + type: string + format: uri + description: This webhook URL (same string as in `webhookUrl`) + circuitState: + type: string + description: > + Delivery state for this URL only. `ok` delivering; `degraded` recent + qualifying fails (still delivering, warning email on the 2nd fail); + `open` skipping most deliveries pending a probe; `half_open` probe + in flight (resume only on HTTP 2xx); `disabled` sticky auto-disabled + until self-serve re-enable (`POST /webhook` / `POST /settings` with + this URL) or a successful probe before sticky disable. + enum: + - ok + - degraded + - open + - half_open + - disabled + reason: + type: string + description: Last qualifying fail reason, e.g. `http_404` or `timeout_or_network` + fails: + type: integer + description: > + Diagnostic only — safe for clients to ignore. Number of qualifying + delivery + + failures in the rolling ~10 minute breaker window (not lifetime, not + "how many + + times the customer retried"). Prefer `circuitState` / + `disabledWebhooks`. + trips: + type: integer + description: > + Diagnostic only — safe for clients to ignore. How many recovery + probes already + + failed for this URL. Probes run on a schedule (≈15 min → 1 h → 6 h); + sticky + + disable after 3 failed probes. The 6 h step is the last probe, not a + blind + + "unblock in 6 hours" timer. + disabledAt: + type: integer + description: Epoch milliseconds when this URL became sticky-disabled + firstFailAt: + type: integer + description: > + Diagnostic only. Epoch ms of the first fail in the current ~10 + minute window + + (pairs with `fails`; not a customer-facing period). + lastStatus: + type: integer + description: Last HTTP status from this URL, when known + nextProbeAt: + type: integer + description: Epoch milliseconds of the next half-open probe, if any + additionalProperties: true + SendMessageRequest: + type: object + required: + - body + properties: + body: + type: string + description: Message text, UTF-8 or UTF-16 string with emoji + minLength: 1 + maxLength: 4096 + example: Hello World 🌍 + quotedMsgId: + type: string + description: Message ID to quote/reply to (Cloud API wamid) + pattern: ^wamid\..+$ + example: wamid.HBgNMTIwMjA3MjEzNjkVAgARGBI5RTBCNUY0QUE2RjZBQzhGNDkA + chatId: + type: string + description: "Recipient chat ID: phone@c.us, group@g.us, or BSUID@lid" + example: 12020721369@c.us + phone: + type: integer + description: Phone number starting with country code (alternative to chatId) + minimum: 1000000000 + maximum: 999999999999999 + example: 12020721369 + additionalProperties: false + description: Request body for sending a text message + SendFileRequest: + type: object + properties: + body: + type: string + description: | + File source (required unless mediaId is set): + - HTTP/HTTPS URL + - Base64 data URI + filename: + type: string + description: File name with extension (required with body, not with mediaId) + mediaId: + type: string + description: WABA media id from uploadMedia (alternative to body) + mediaType: + type: string + enum: + - image + - video + - audio + - document + description: Required when using mediaId + voice: + type: boolean + description: Native WhatsApp voice note (audio/ogg only) + caption: + type: string + maxLength: 1024 + quotedMsgId: + type: string + chatId: + type: string + phone: + type: integer + additionalProperties: true + description: Send file by URL/base64 or by mediaId + responses: + InvalidToken: + description: Invalid or missing authentication token + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + InternalError: + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + MessageSent: + description: Message sent successfully + content: + application/json: + schema: + $ref: "#/components/schemas/MessageSentResponse" + BadRequest: + description: Invalid request parameters + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + TooManyRequests: + description: Rate limit exceeded + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + Success: + description: Operation successful + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + securitySchemes: + tokenAuth: + type: apiKey + in: query + name: token + description: JWT token or API key + requestBodies: {} +security: + - tokenAuth: [] diff --git a/quality/generator/provenance.json b/quality/generator/provenance.json new file mode 100644 index 0000000..e2f1ac3 --- /dev/null +++ b/quality/generator/provenance.json @@ -0,0 +1,110 @@ +{ + "sourceRepository": "https://github.com/1msg/1msg-api", + "sourceCommit": "888ee40a635ab19dbff4c101b8d4329790c7254f", + "generatorVersion": "7.22.0", + "generatorSha256": "3f1e6ce5c6ad4f15242c6170ab43aad4bad771622617eeece4a7d4f72ffaf329", + "contractSha256": "b26aa068f67c892144f2f9f2d9d0ce7a39bb12ff8ad01fd52e68f950fcc2f18c", + "sourceFiles": { + "gen/bundle-public.js": "9b772bb8d1801ef986d8a0a6b0324a8e867fbb961b56549f812e7414223bdf68", + "public/openapi.yaml": "5010623f5ab269355b2b6dc11d9b4d47d1e392d9cb366cef66cbbd8239c3ab2b", + "public/paths/calling/initiateCall.yaml": "82febe8ab1ff895e78a522ef23f943507fa6978a3867f4f7d2b4cdfa07109b77", + "public/paths/calling/callingSettings.yaml": "8f1ff6184a953c190d025f43bdd5ecc85fea2d8e30423b3cf0d381d539c41cf7", + "public/paths/groups/groups_groupId_invite_link.yaml": "8ddcc592bbb8f47e099e11f4d7cc75b91ff79296eaa35130308a1e29c1794836", + "public/paths/groups/groups.yaml": "f595e2f5e147f44a7278fe928154e9a8401a8e28d4760963ae5c2b8e197bf6f4", + "public/paths/groups/groups_groupId.yaml": "48f002f2b8f64e5dca4abfd634c5eb9e2cde2498fe32e44ca1dbc3e3f4fc19f5", + "public/paths/channel/settings.yaml": "e2893c6ce65399cb1b2f260dc9c67b062b3cc1af50213af3cd9deab77205f261", + "public/paths/channel/commerce.yaml": "6b43175a6d9ba928c4cc65033a5933d4d2f2a7f65471dafa07112d058dbb2e1f", + "public/paths/channel/status.yaml": "9670a21034685cdd79fb28b92dbec38feb74f8255df5bbf76a02d23ea0834841", + "public/paths/channel/mmLiteStatus.yaml": "3cb8b6f1dfbc8b028408cf792268af1984ee38e4362e71d809e3ec438cb26d38", + "public/paths/channel/conversationalAutomation.yaml": "2509e0ae34e8d19bc83dc47bb4da584a4a3653f7c7391c17a372e09fe1a68d4c", + "public/paths/channel/whatsappBusinessEncryption.yaml": "62bd8c98b8a3970d9b2a8afbde9a24197cf3e3ab3d075c633330e67c58480fd1", + "public/paths/profile/me.yaml": "c1dc83a56b3d843cd0cced9345904bea65413c3a6b50445baa5d0c7efe2958c2", + "public/paths/users/blockUser.yaml": "334c133da8bac1f3c1ce2c1642b526ad1bd44b2cbd0a91430a36cc0cc57dbdfb", + "public/paths/users/blockedUsers.yaml": "6f86fa8a90fac5e423cb0e267b13503466c42d669c5d77c1f2b0dd43920ab201", + "public/paths/users/unblockUser.yaml": "84fa3721451121872fee2ee7505c94b603a3af2045ca6f774208d25f151c28d1", + "public/paths/templates/templates.yaml": "f6e41fb5b90dca2a80c4eac4d052c51e6846919b95eee37f401b35a642cdfda6", + "public/paths/templates/removeTemplate.yaml": "9c5cfe2f8d51e488cfc957c4bc7c4fb9a8599caf0ec37c53e61891f8eccfc303", + "public/paths/templates/addTemplate.yaml": "a242c132f53885418dba9d718be2690473d3da88955acd705da27b689773e419", + "public/paths/templates/sendTemplate.yaml": "29b4bb0e3793f1f05ec259fb465ceadd942b683da7d09e80faf4156110d2e253", + "public/paths/webhooks/webhook.yaml": "041b37e4a6702de79bb1669ec7ea406e560ca18b7d97aba24d4a4fb0ebbdce72", + "public/paths/messaging/uploadMedia.yaml": "4d7899c88220fcf712667ee3584f93006bd0dcc0de663a54de53409a46f3a9b5", + "public/paths/messaging/sendOrderDetails.yaml": "7e27336c33ca83b575ef6e02445a5196664455f48a55d1755179bb2e36ffc4d9", + "public/paths/messaging/sendMessage.yaml": "5599e639be4dd34414649a7d5faf0d647599cb203d0e95a14f7ae660d6ade6ec", + "public/paths/messaging/sendAddressMessage.yaml": "e759d10dbe389068ff3a0d06e03d93e1616cdbfdc6c2c1c6767270bd31bb6265", + "public/paths/messaging/sendSticker.yaml": "ff7f7b7df63ec75fd5098e3616fd903e92d2ac86bdf3ce6bd08c78450ffabf1b", + "public/paths/messaging/sendContact.yaml": "509e1535bc405bce49a2efaf0fc812293042f338e8c42e26376c06b06e2cf194", + "public/paths/messaging/media-id.yaml": "5afa9603d73d4771348544c80638c46785cc75aa1388808b84fdeb90051e8172", + "public/paths/messaging/sendProduct.yaml": "1871d3e9e4686e76a3ed30f111ea7619cb8c22665e679b6266390014fbb10b9d", + "public/paths/messaging/sendCarousel.yaml": "f188681458f3afdfc9846863a79d5ea28b6756cb1a5a00641bb9a29a332aad70", + "public/paths/messaging/sendLocationRequest.yaml": "b207ed18f773276c39c7bd854ee2c853071bcba244762d5a678e361b7d706446", + "public/paths/messaging/sendReaction.yaml": "65abf2bde681ca8e32b49ec273125f3e4aa41deb3d09873fa87b17e621da946f", + "public/paths/messaging/sendFile.yaml": "6c07d60b36c8a415cab43c61a706aed4a73a53e52a114d50d8fbebc733296530", + "public/paths/messaging/deleteMedia.yaml": "00c09f041df7aa0a49ccdd60122cb6855a89386594676d4fe523bec442c0b4ca", + "public/paths/messaging/messages.yaml": "d99ba398d05acca8ecb817d9b9806b497dea9bbdb079e280c0bcda1bad966b0d", + "public/paths/messaging/retrieveMedia.yaml": "4c73b3992f4653a4b3155be742b6d6720d79a454a17f0f3fbdc9e20d83cc5d01", + "public/paths/messaging/sendPaymentRequest.yaml": "2c83ccf1b20bc0dbae956e2fc445f981cdeac2be742c80b7b4db472f539d8afe", + "public/paths/messaging/sendLocation.yaml": "1f34da40ea89af2a693affffec822fc59663f4efe1554136817dd83fda3ae2ff", + "public/paths/messaging/sendButton.yaml": "5fc74240b27f216c65b45da4975b47e675c6ca4e3da7b204c27d67242566dcc3", + "public/paths/messaging/sendList.yaml": "16cfc200444319d4280a801926d31d0acabbe917bea986460f54ad129f91fcd6", + "public/paths/messaging/readMessage.yaml": "f35a04e3e6a8b115b208f0699ff67503a996284f417cea42efe8d51fc323cb36", + "public/paths/messaging/sendCtaUrl.yaml": "2935101dab612c8289aed85fed0e4900e6eb7a67ef1404000d115ecfefdc23f2", + "public/paths/messaging/sendFlow.yaml": "6add518a4650aa1d507aebe2053cfb53559d6c313fea0f2e1f7c04d4582ebd76", + "public/paths/flows/flows_flowId_preview.yaml": "a838105c68ffaa7b93c2d78d0ddeba7c5a325fef5fe2e7699b115139bd4e422c", + "public/paths/flows/flows_flowId_assets.yaml": "637f3d977b840dc2c804585234f173fb917735fc77f879f785011cbc06c81cf1", + "public/paths/flows/flows_flowId_publish.yaml": "b39e31eafb8a64c4ae74bd3de0aa915ece2f854fa654dc2810cc29ea51586af8", + "public/paths/flows/flows.yaml": "9e5a75c523d7c149412c9e9d4863b7f5dfc3240eb443c1498e420c02eaef2e7f", + "public/paths/flows/flows_flowId.yaml": "d6a84944203deb528081980f8213291d694a42944e21e6df889dbd9158f8ff8e", + "public/paths/flows/flows_flowId_deprecate.yaml": "f2242d190723ee11ed540d962c82b3e7ad9f3d017f75f5bdbd4d02dc9cb7b65e", + "public/paths/flows/flows_flowId_metadata.yaml": "297b8c9059f17b2a5a61c4bab80b112f51304e0659956ba04fc29565e97cb3ef", + "shared/responses/MessageSent.yaml": "0aca0872bb784a7039ff8be7ef57fc13c91638240624831249eeda7aa95704be", + "shared/responses/Success.yaml": "8c4363edb30103d41fbf7bcb8c9bc97782c76611a2bfcd2dbdd48081a2f4b813", + "shared/responses/TooManyRequests.yaml": "330a80e797769b544ed5c434623ba658d9d68bb66a554c560339d12e4266ce7c", + "shared/responses/InvalidToken.yaml": "be7e20df9dfa90f128897053856f768a676acc685906a37445bfc625df0854af", + "shared/responses/InternalError.yaml": "0b7bee775301c9c6aca8f8c665214a08b3e856b5c5eeeb57c036ef22b48f2407", + "shared/responses/BadRequest.yaml": "ef65a9cde8edb7870bf4bf28b6595b1e37f0dd3520faa877f71b6d3d732865d4", + "shared/schemas/ErrorResponse.yaml": "2e2745599a88a23228168b585743e25c6a04f971e4aa319198539a9af0006503", + "shared/schemas/WebhookInfo.yaml": "22a6eecc886d3212ff55c7fb36e5a2f7ae7084666b0e7df79ebb308189afe3b8", + "shared/schemas/FlowInfo.yaml": "9a9f9d8b67420768fdb95170af04eea56f86a729fe6e4b8e55ffe6bb866a7ebb", + "shared/schemas/InitiateCallRequest.yaml": "f3300ec43cd4074afaf38f4e9d3695251ae1e1c1855fe5babb0253b23cb8b30b", + "shared/schemas/ChannelStatusDetailed.yaml": "63cf817f0ae8bda5850b64e2ca24a3cf5867e5e1fe1383ca30ad16cc1d0fe385", + "shared/schemas/SuccessResponse.yaml": "7dbb8695c11212213b86d6b8ddd0d6453e5630891735db447273014b3ae0b53c", + "shared/schemas/ProfileInfo.yaml": "4efee312cd1a86f6bfd06655d800cb156fad93d038f3b49fc52d296be2995207", + "shared/schemas/CallingSettings.yaml": "def3877472b9ed0bacfe9666d22c9bce30bc6b29d7433528ed4bffd471a9c5f5", + "shared/schemas/ConversationalAutomation.yaml": "b918c15cdb9cebb64075fd93c680c6dec48e713245d36535c0c5b423e1522602", + "shared/schemas/WebhookUrlStatus.yaml": "3e52f8356f7795966f9ef68d36c0b7c3d88ee00ad7abac58f9e4b85a46ddc766", + "shared/schemas/StatisticsResponse.yaml": "bd908f2527dc7bfcb41bda15a5748b26210f2bc09a9fa0f24fea7498c9342715", + "shared/schemas/InitiateCallResponse.yaml": "eeb204a62e2b611327a510cc9f714b5fcdf4914bf96f44a7691d050bba48b5aa", + "shared/schemas/MessageSentResponse.yaml": "2dfb0257aafe1d9a7a3697088323909ebd74ac3f61520770e227e5f7b34aad43", + "shared/schemas/ChannelStatus.yaml": "7a95f1b01d56390f14005349b59c76d576f179b581587628f057ff5d6e60bb35", + "shared/parameters/flowId.yaml": "5553440629ce9916e4191be9d67c5b115914cf7bc53eba5f9753fe2233e459c5", + "shared/parameters/date.yaml": "9db4dd8c143a365d139971a4208745646284da7c59f30320cd1958e27685b32a", + "shared/parameters/group_id.yaml": "72da018aeabdf5e1f02c07405b98ece7b59f01152dfff38d026bd565c62486ee", + "shared/parameters/template_external_id.yaml": "2f3d2bf4340c7e47e171e28068ed0a9cf956c48f3b84ca79b6f6fa23f1cfe76b", + "shared/schemas/requests/SendContactRequest.yaml": "02b7a66eb96273183d73ff8934d5a7ae3fdcda891bb7868b1f4b5473c8cae569", + "shared/schemas/requests/ReadMessageRequest.yaml": "e1cbb41a16912c5f0c857af5046708804e7efb0b460b09df22b41c0959dd7666", + "shared/schemas/requests/SendCarouselRequest.yaml": "ddaa58dbb472eea48d291add1354a47e8fce4fc2d6a92641cf5175889cf5eb03", + "shared/schemas/requests/SendReactionRequest.yaml": "d06f0d5f96b9d7d2b6f7ad36ccf5288d0933458ffcf9ba711e02246108f8f9fc", + "shared/schemas/requests/SendFileRequest.yaml": "c47eca1d90b15997ce9b1e955694e8437ca66a141df62dce997921bdf84c2b00", + "shared/schemas/requests/SendLocationRequest.yaml": "9a3a90dd091093680a45dc5ee0b260f48f8b2822e7c74cbc3a6007135bdd05e2", + "shared/schemas/requests/SendProductRequest.yaml": "f6748ab368cf809b4ce9d0fe253466e46a2501390fe4fbc129fe235a1b51fc66", + "shared/schemas/requests/SendButtonRequest.yaml": "d23b38055c5d512bb892706ae323ffeb7454c60d6ad0e78692908bf8c4b38702", + "shared/schemas/requests/SendListRequest.yaml": "5de384d53c241635aa22fbd397db4b2007d2fb2ad04ed32f53cc845117d46b83", + "shared/schemas/requests/SendMessageRequest.yaml": "ee9cd3b8fa8392cabba39ed7307aa9fa93b9485350549f66695560c39eea4b16", + "shared/schemas/requests/UploadMediaRequest.yaml": "ad2639c9bb58140b3b8bc7e05324aa9fb6f661ebada33a327ffc1b856b64dec3" + }, + "language": "cpp", + "generatorName": "cpp-restsdk", + "additionalProperties": { + "packageName": "one-msg-sdk", + "packageVersion": "1.0.1", + "apiPackage": "onemsg.sdk.api", + "modelPackage": "onemsg.sdk.model" + }, + "roots": [ + "include/", + "src/", + "CMakeLists.txt", + "Config.cmake.in" + ], + "postprocess": true +} diff --git a/quality/generator/verify-negative.mjs b/quality/generator/verify-negative.mjs new file mode 100644 index 0000000..993a151 --- /dev/null +++ b/quality/generator/verify-negative.mjs @@ -0,0 +1,59 @@ +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { readFileSync, rmSync, writeFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +const root = resolve(dirname(fileURLToPath(import.meta.url)), "../.."); +const inventory = JSON.parse( + readFileSync(join(root, "quality/generator/inventory.json"), "utf8"), +); +// Use a generated directory member so the extra-file fixture exercises the same recursive output scope. +const path = Object.keys(inventory).find((file) => file.startsWith("include/")); +assert.ok(path, "generation inventory cannot be empty"); +const original = readFileSync(join(root, path)); +const ignored = join( + dirname(path), + `.quality-untracked${path.slice(path.lastIndexOf("."))}`, +); +const ignorePath = join(root, ".gitignore"); +const originalIgnore = readFileSync(ignorePath); +/** Require the real generation replay to fail specifically on output drift, not a missing tool or configuration. */ +function rejectDrift() { + const result = spawnSync( + process.execPath, + ["quality/generator/generate.mjs"], + { cwd: root, encoding: "utf8", timeout: 120000 }, + ); + assert.notEqual(result.status, 0, "generation accepted modified output"); + assert.match( + result.stderr + result.stdout, + /Generated drift/, + "fixture failed for an unrelated reason", + ); +} +try { + writeFileSync( + join(root, path), + Buffer.concat([ + original, + Buffer.from("\n// negative output drift fixture\n"), + ]), + ); + rejectDrift(); + rmSync(join(root, path)); + rejectDrift(); + writeFileSync(join(root, path), original); + writeFileSync( + ignorePath, + Buffer.concat([originalIgnore, Buffer.from(`\n/${ignored}\n`)]), + ); + writeFileSync(join(root, ignored), "unexpected ignored generated output"); + rejectDrift(); + console.log( + "Real regeneration rejects changed, deleted and ignored/untracked output", + ); +} finally { + writeFileSync(join(root, path), original); + writeFileSync(ignorePath, originalIgnore); + rmSync(join(root, ignored), { force: true }); +} diff --git a/quality/postprocess.mjs b/quality/postprocess.mjs new file mode 100644 index 0000000..c15a0a2 --- /dev/null +++ b/quality/postprocess.mjs @@ -0,0 +1,107 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +/** + * Replace only the two broken string/object union models produced by OpenAPI + * Generator 7.22 (escaped C++ template names and primitive method calls). + * The template preserves VariantType/getVariant/setVariant and adds ModelBase + * compatibility required by generated multipart/form request builders. + */ +const ownRoot = fileURLToPath(new URL("..", import.meta.url)); +const root = process.argv[2] ? resolve(process.argv[2]) : ownRoot; +const template = await readFile( + resolve(ownRoot, "quality/templates/flow-header.h"), + "utf8", +); +const unions = [ + ["SendFlow_request_header", "std::shared_ptr", "is_object"], + ["SendFlow_request_1_header", "std::shared_ptr", "is_object"], + [ + "CreateSettings_request_webhookUrl", + "std::vector", + "is_array", + ], + [ + "GetWebhook_200_response_webhookUrl", + "std::vector", + "is_array", + ], + [ + "ListSettings_200_response_webhookUrl", + "std::vector", + "is_array", + ], + [ + "SetWebhook_200_response_webhookUrl", + "std::vector", + "is_array", + ], + [ + "SetWebhook_request_webhookUrl", + "std::vector", + "is_array", + ], + [ + "SendContact_request_contact_name", + "std::map>", + "is_object", + ], +]; +for (const [name, alternative, kind] of unions) { + const header = resolve(root, `include/one-msg-sdk/model/${name}.h`); + await readFile(header); + const validation = + alternative === "std::shared_ptr" + ? ' if (std::holds_alternative>(m_variantValue) && !std::get>(m_variantValue)) throw std::invalid_argument("Flow header cannot be null");' + : " // Every stored alternative is a value; JSON null is rejected by fromJson."; + await writeFile( + header, + template + .replaceAll("@NAME@", name) + .replaceAll("@ALTERNATIVE@", alternative) + .replaceAll("@KIND@", kind) + .replaceAll("@VALIDATE@", validation), + ); + await writeFile( + resolve(root, `src/model/${name}.cpp`), + `// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates.\n#include "one-msg-sdk/model/${name}.h"\n`, + ); +} +const clientPath = resolve(root, "include/one-msg-sdk/ApiClient.h"); +const client = await readFile(clientPath, "utf8"); +const mapAnchor = + " static utility::string_t parameterToString(const ModelBase& value);"; +const mapMarker = "// 1MSG: map form values use generated JSON serializers."; +if (!client.includes(mapMarker)) { + if (!client.includes(mapAnchor)) + throw new Error("C++ request serializer changed"); + await writeFile( + clientPath, + client.replace( + mapAnchor, + `${mapAnchor}\n ${mapMarker}\n template\n static utility::string_t parameterToString(const std::map& value) {\n return ModelBase::toJson(value).serialize();\n }`, + ), + ); +} + +const cmakePath = resolve(root, "CMakeLists.txt"); +let cmake = await readFile(cmakePath, "utf8"); +if (!cmake.includes("find_package(OpenSSL REQUIRED)")) + cmake = cmake.replace( + "find_package(Boost REQUIRED)", + "find_package(Boost REQUIRED)\nfind_package(OpenSSL REQUIRED)", + ); +cmake = cmake.replace( + "PUBLIC Boost::headers cpprestsdk::cpprest)", + "PUBLIC Boost::headers cpprestsdk::cpprest OpenSSL::SSL OpenSSL::Crypto)", +); +await writeFile(cmakePath, cmake); +const packagePath = resolve(root, "Config.cmake.in"); +let packageConfig = await readFile(packagePath, "utf8"); +if (!packageConfig.includes("find_dependency(OpenSSL)")) + packageConfig = packageConfig.replace( + "@PACKAGE_INIT@", + "@PACKAGE_INIT@\n\ninclude(CMakeFindDependencyMacro)\nfind_dependency(Boost)\nfind_dependency(cpprestsdk)\nfind_dependency(OpenSSL)", + ); +await writeFile(packagePath, packageConfig); diff --git a/quality/templates/flow-header.h b/quality/templates/flow-header.h new file mode 100644 index 0000000..aab0db0 --- /dev/null +++ b/quality/templates/flow-header.h @@ -0,0 +1,63 @@ +// Generated by the pinned 1MSG compatibility producer in quality/postprocess.mjs. +#pragma once +#include "one-msg-sdk/ModelBase.h" +#include "one-msg-sdk/Object.h" +#include "one-msg-sdk/AnyType.h" +#include +#include + +namespace onemsg { namespace sdk { namespace model { + +/** Preserve the contract's string-or-structured-value union without invalid generator casts. */ +class @NAME@ : public ModelBase { +public: + using VariantType = std::variant<@ALTERNATIVE@, utility::string_t>; + + /** Return the selected wire representation; no transport or global state is touched. */ + const VariantType& getVariant() const { return m_variantValue; } + /** Replace the selected representation; validate before sending an object pointer. */ + void setVariant(VariantType value) { m_variantValue = std::move(value); } + /** Reject null object pointers because the OpenAPI union is not nullable. */ + void validate() override { +@VALIDATE@ + } + /** Serialize the active alternative using the same converters as generated models. */ + web::json::value toJson() const override { + return std::visit([](const auto& value) { return ModelBase::toJson(value); }, m_variantValue); + } + /** Accept only the two schema alternatives and leave the previous value intact on mismatch. */ + bool fromJson(const web::json::value& json) override { + if (json.is_string()) { m_variantValue = json.as_string(); return true; } + if (json.@KIND@()) { @ALTERNATIVE@ value; if (!ModelBase::fromJson(json, value)) return false; m_variantValue = std::move(value); return true; } + return false; + } + /** Retain the generated explicit-alternative API while using converters that support primitives. */ + template bool fromJson(const web::json::value& json) { + Target target; + if (!ModelBase::fromJson(json, target)) return false; + m_variantValue = std::move(target); + return true; + } + /** Write the union as one JSON part, preserving nested object fields. */ + void toMultipart(std::shared_ptr multipart, const utility::string_t& name) const override { + multipart->add(ModelBase::toHttpContent(name, toJson())); + } + /** Decode the named JSON part through the same union validation used by JSON requests. */ + bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) override { + if (!multipart->hasContent(name)) return false; + web::json::value json; + return ModelBase::fromHttpContent(multipart->getContent(name), json) && fromJson(json); + } + /** Retain typed multipart decoding for existing clients that explicitly select an alternative. */ + template bool fromMultiPart(std::shared_ptr multipart, const utility::string_t& name) { + if (!multipart->hasContent(name)) return false; + Target target; + if (!ModelBase::fromHttpContent(multipart->getContent(name), target)) return false; + m_variantValue = std::move(target); + return true; + } +protected: + VariantType m_variantValue; +}; + +} } } diff --git a/quality/tests/contract.cpp b/quality/tests/contract.cpp new file mode 100644 index 0000000..3667176 --- /dev/null +++ b/quality/tests/contract.cpp @@ -0,0 +1,42 @@ +#include "one-msg-sdk/model/SendMessageRequest.h" +#include "one-msg-sdk/model/SendFlow_request_header.h" +#include "one-msg-sdk/model/SetWebhook_request_webhookUrl.h" +#include "one-msg-sdk/ApiClient.h" +#include +#include + +/** Verify generated JSON field names and optional omission without contacting a service. */ +int main() { + using onemsg::sdk::model::SendMessageRequest; + SendMessageRequest request; + request.setBody(utility::conversions::to_string_t("hello")); + request.setChatId(utility::conversions::to_string_t("12020721369@c.us")); + const auto json = request.toJson(); + if (json.at(utility::conversions::to_string_t("body")).as_string() != utility::conversions::to_string_t("hello") || json.at(utility::conversions::to_string_t("chatId")).as_string() != utility::conversions::to_string_t("12020721369@c.us")) { + throw std::runtime_error("request wire names changed"); + } + if (json.has_field(utility::conversions::to_string_t("phone")) || json.has_field(utility::conversions::to_string_t("quotedMsgId"))) { + throw std::runtime_error("unset optional fields must be omitted"); + } + SendMessageRequest decoded; + if (!decoded.fromJson(json) || decoded.getBody() != request.getBody() || decoded.getChatId() != request.getChatId()) { + throw std::runtime_error("request JSON does not round-trip"); + } + onemsg::sdk::model::SendFlow_request_header header; + const auto headerText = web::json::value::string(utility::conversions::to_string_t("header text")); + if (!header.fromJson(headerText) || header.toJson() != headerText) throw std::runtime_error("string union alternative lost"); + auto headerObject = web::json::value::object(); + headerObject[utility::conversions::to_string_t("text")] = headerText; + if (!header.fromJson(headerObject) || header.toJson() != headerObject) throw std::runtime_error("object union alternative lost"); + if (header.fromJson(web::json::value::null())) throw std::runtime_error("non-nullable union accepted null"); + onemsg::sdk::model::SetWebhook_request_webhookUrl webhook; + auto urls = web::json::value::array(2); + urls[0] = web::json::value::string(utility::conversions::to_string_t("https://example.test/one")); + urls[1] = web::json::value::string(utility::conversions::to_string_t("https://example.test/two")); + if (!webhook.fromJson(urls) || webhook.toJson() != urls) throw std::runtime_error("webhook array union lost"); + if (webhook.fromJson(web::json::value::number(42))) throw std::runtime_error("webhook union accepted invalid type"); + const std::map names{{utility::conversions::to_string_t("formatted_name"), utility::conversions::to_string_t("Contact")}}; + const auto parameter = onemsg::sdk::api::ApiClient::parameterToString(names); + if (!web::json::value::parse(parameter).is_object()) throw std::runtime_error("map form field must remain JSON"); + std::cout << "offline SDK contract smoke passed\n"; +} diff --git a/src/AnyType.cpp b/src/AnyType.cpp index 547afd8..9917a96 100644 --- a/src/AnyType.cpp +++ b/src/AnyType.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/ApiClient.cpp b/src/ApiClient.cpp index 5d40318..8e35835 100644 --- a/src/ApiClient.cpp +++ b/src/ApiClient.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/ApiConfiguration.cpp b/src/ApiConfiguration.cpp index facb2f9..6e02956 100644 --- a/src/ApiConfiguration.cpp +++ b/src/ApiConfiguration.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/ApiException.cpp b/src/ApiException.cpp index f23caf3..83820dc 100644 --- a/src/ApiException.cpp +++ b/src/ApiException.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/HttpContent.cpp b/src/HttpContent.cpp index cec1990..607ba33 100644 --- a/src/HttpContent.cpp +++ b/src/HttpContent.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/JsonBody.cpp b/src/JsonBody.cpp index 0b3d405..7d1595f 100644 --- a/src/JsonBody.cpp +++ b/src/JsonBody.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/ModelBase.cpp b/src/ModelBase.cpp index 9c74fdd..180df13 100644 --- a/src/ModelBase.cpp +++ b/src/ModelBase.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/MultipartFormData.cpp b/src/MultipartFormData.cpp index adf2d30..3cc455a 100644 --- a/src/MultipartFormData.cpp +++ b/src/MultipartFormData.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/Object.cpp b/src/Object.cpp index 7b9c792..42a5f83 100644 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/api/CallingApi.cpp b/src/api/CallingApi.cpp index 3e03f31..b867e2a 100644 --- a/src/api/CallingApi.cpp +++ b/src/api/CallingApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/api/CatalogApi.cpp b/src/api/CatalogApi.cpp index a8dfbd6..fad01ed 100644 --- a/src/api/CatalogApi.cpp +++ b/src/api/CatalogApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/api/ChannelApi.cpp b/src/api/ChannelApi.cpp index 86d1808..c28b912 100644 --- a/src/api/ChannelApi.cpp +++ b/src/api/ChannelApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -35,6 +35,167 @@ ChannelApi::~ChannelApi() { } +pplx::task>> ChannelApi::createSettings(utility::string_t token, std::shared_ptr createSettingsRequest) const +{ + + // verify the required parameter 'createSettingsRequest' is set + if (createSettingsRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'createSettingsRequest' when calling ChannelApi->createSettings")); + } + + + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); + utility::string_t localVarPath = utility::conversions::to_string_t("/settings"); + + std::map localVarQueryParams; + std::map localVarHeaderParams( localVarApiConfiguration->getDefaultHeaders() ); + std::map localVarFormParams; + std::map> localVarFileParams; + + std::unordered_set localVarResponseHttpContentTypes; + localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); + + utility::string_t localVarResponseHttpContentType; + + // use JSON if possible + if ( localVarResponseHttpContentTypes.size() == 0 ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("application/json"); + } + // JSON + else if ( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarResponseHttpContentTypes.end() ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("application/json"); + } + // multipart formdata + else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarResponseHttpContentTypes.end() ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + } + else + { + throw ApiException(400, utility::conversions::to_string_t("ChannelApi->createSettings does not produce any supported media type")); + } + + localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; + + std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); + + { + localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); + } + + std::shared_ptr localVarHttpBody; + utility::string_t localVarRequestHttpContentType; + + // use JSON if possible + if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(createSettingsRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); + } + // multipart formdata + else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(createSettingsRequest.get()) + { + createSettingsRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("createSettingsRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); + } + else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("application/x-www-form-urlencoded"); + } + else + { + throw ApiException(415, utility::conversions::to_string_t("ChannelApi->createSettings does not consume any supported media type")); + } + + // authentication (tokenAuth) required + { + utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("tokenAuth")); + if ( localVarApiKey.size() > 0 ) + { + localVarQueryParams[utility::conversions::to_string_t("token")] = localVarApiKey; + } + } + + return m_ApiClient->callApi(localVarPath, utility::conversions::to_string_t("POST"), localVarQueryParams, localVarHttpBody, localVarHeaderParams, localVarFormParams, localVarFileParams, localVarRequestHttpContentType) + .then([=, this](web::http::http_response localVarResponse) + { + if (m_ApiClient->getResponseHandler()) + { + m_ApiClient->getResponseHandler()(localVarResponse.status_code(), localVarResponse.headers()); + } + + // 1xx - informational : OK + // 2xx - successful : OK + // 3xx - redirection : OK + // 4xx - client error : not OK + // 5xx - client error : not OK + if (localVarResponse.status_code() >= 400) + { + throw ApiException(localVarResponse.status_code() + , utility::conversions::to_string_t("error calling createSettings: ") + localVarResponse.reason_phrase() + , std::make_shared(localVarResponse.extract_utf8string(true).get())); + } + + // check response content type + if(localVarResponse.headers().has(utility::conversions::to_string_t("Content-Type"))) + { + utility::string_t localVarContentType = localVarResponse.headers()[utility::conversions::to_string_t("Content-Type")]; + if( localVarContentType.find(localVarResponseHttpContentType) == std::string::npos ) + { + throw ApiException(500 + , utility::conversions::to_string_t("error calling createSettings: unexpected response type: ") + localVarContentType + , std::make_shared(localVarResponse.extract_utf8string(true).get())); + } + } + + return localVarResponse.extract_string(); + }) + .then([=, this](utility::string_t localVarResponse) + { + std::map> localVarResult; + + if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) + { + web::json::value localVarJson = web::json::value::parse(localVarResponse); + + for( auto& localVarItem : localVarJson.as_object() ) + { + std::shared_ptr localVarItemObj; + ModelBase::fromJson(localVarItem.second, localVarItemObj); + localVarResult[localVarItem.first] = localVarItemObj; + } + } + // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) + // { + // TODO multipart response parsing + // } + else + { + throw ApiException(500 + , utility::conversions::to_string_t("error calling createSettings: unsupported response type")); + } + + return localVarResult; + }); +} pplx::task> ChannelApi::getConversationalAutomation(utility::string_t token) const { @@ -168,7 +329,7 @@ pplx::task> ChannelApi::getConversatio return localVarResult; }); } -pplx::task>> ChannelApi::getStatus(utility::string_t token) const +pplx::task> ChannelApi::getStatus(utility::string_t token) const { @@ -280,19 +441,147 @@ pplx::task>> ChannelApi::ge }) .then([=, this](utility::string_t localVarResponse) { - std::map> localVarResult; + std::shared_ptr localVarResult(new GetStatus_200_response()); if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) { web::json::value localVarJson = web::json::value::parse(localVarResponse); - for( auto& localVarItem : localVarJson.as_object() ) + ModelBase::fromJson(localVarJson, localVarResult); + } + // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) + // { + // TODO multipart response parsing + // } + else + { + throw ApiException(500 + , utility::conversions::to_string_t("error calling getStatus: unsupported response type")); + } + + return localVarResult; + }); +} +pplx::task> ChannelApi::listSettings(utility::string_t token) const +{ + + + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); + utility::string_t localVarPath = utility::conversions::to_string_t("/settings"); + + std::map localVarQueryParams; + std::map localVarHeaderParams( localVarApiConfiguration->getDefaultHeaders() ); + std::map localVarFormParams; + std::map> localVarFileParams; + + std::unordered_set localVarResponseHttpContentTypes; + localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); + + utility::string_t localVarResponseHttpContentType; + + // use JSON if possible + if ( localVarResponseHttpContentTypes.size() == 0 ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("application/json"); + } + // JSON + else if ( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarResponseHttpContentTypes.end() ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("application/json"); + } + // multipart formdata + else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarResponseHttpContentTypes.end() ) + { + localVarResponseHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + } + else + { + throw ApiException(400, utility::conversions::to_string_t("ChannelApi->listSettings does not produce any supported media type")); + } + + localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; + + std::unordered_set localVarConsumeHttpContentTypes; + + { + localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); + } + + std::shared_ptr localVarHttpBody; + utility::string_t localVarRequestHttpContentType; + + // use JSON if possible + if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + } + // multipart formdata + else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + } + else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) + { + localVarRequestHttpContentType = utility::conversions::to_string_t("application/x-www-form-urlencoded"); + } + else + { + throw ApiException(415, utility::conversions::to_string_t("ChannelApi->listSettings does not consume any supported media type")); + } + + // authentication (tokenAuth) required + { + utility::string_t localVarApiKey = localVarApiConfiguration->getApiKey(utility::conversions::to_string_t("tokenAuth")); + if ( localVarApiKey.size() > 0 ) + { + localVarQueryParams[utility::conversions::to_string_t("token")] = localVarApiKey; + } + } + + return m_ApiClient->callApi(localVarPath, utility::conversions::to_string_t("GET"), localVarQueryParams, localVarHttpBody, localVarHeaderParams, localVarFormParams, localVarFileParams, localVarRequestHttpContentType) + .then([=, this](web::http::http_response localVarResponse) + { + if (m_ApiClient->getResponseHandler()) + { + m_ApiClient->getResponseHandler()(localVarResponse.status_code(), localVarResponse.headers()); + } + + // 1xx - informational : OK + // 2xx - successful : OK + // 3xx - redirection : OK + // 4xx - client error : not OK + // 5xx - client error : not OK + if (localVarResponse.status_code() >= 400) + { + throw ApiException(localVarResponse.status_code() + , utility::conversions::to_string_t("error calling listSettings: ") + localVarResponse.reason_phrase() + , std::make_shared(localVarResponse.extract_utf8string(true).get())); + } + + // check response content type + if(localVarResponse.headers().has(utility::conversions::to_string_t("Content-Type"))) + { + utility::string_t localVarContentType = localVarResponse.headers()[utility::conversions::to_string_t("Content-Type")]; + if( localVarContentType.find(localVarResponseHttpContentType) == std::string::npos ) { - std::shared_ptr localVarItemObj; - ModelBase::fromJson(localVarItem.second, localVarItemObj); - localVarResult[localVarItem.first] = localVarItemObj; + throw ApiException(500 + , utility::conversions::to_string_t("error calling listSettings: unexpected response type: ") + localVarContentType + , std::make_shared(localVarResponse.extract_utf8string(true).get())); } } + + return localVarResponse.extract_string(); + }) + .then([=, this](utility::string_t localVarResponse) + { + std::shared_ptr localVarResult(new ListSettings_200_response()); + + if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) + { + web::json::value localVarJson = web::json::value::parse(localVarResponse); + + ModelBase::fromJson(localVarJson, localVarResult); + } // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) // { // TODO multipart response parsing @@ -300,7 +589,7 @@ pplx::task>> ChannelApi::ge else { throw ApiException(500 - , utility::conversions::to_string_t("error calling getStatus: unsupported response type")); + , utility::conversions::to_string_t("error calling listSettings: unsupported response type")); } return localVarResult; diff --git a/src/api/FlowsApi.cpp b/src/api/FlowsApi.cpp index fdba1ea..bb39e08 100644 --- a/src/api/FlowsApi.cpp +++ b/src/api/FlowsApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -35,9 +35,15 @@ FlowsApi::~FlowsApi() { } -pplx::task> FlowsApi::createFlows(utility::string_t token, boost::optional wabaAccountId) const +pplx::task> FlowsApi::createFlows(utility::string_t token, std::shared_ptr createFlowsRequest, boost::optional wabaAccountId) const { + // verify the required parameter 'createFlowsRequest' is set + if (createFlowsRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'createFlowsRequest' when calling FlowsApi->createFlows")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/flows"); @@ -75,6 +81,7 @@ pplx::task> FlowsApi::createFlows(uti localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); @@ -91,11 +98,27 @@ pplx::task> FlowsApi::createFlows(uti if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(createFlowsRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } // multipart formdata else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(createFlowsRequest.get()) + { + createFlowsRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("createFlowsRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); } else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) { @@ -1010,7 +1033,7 @@ pplx::task> FlowsApi return localVarResult; }); } -pplx::task> FlowsApi::listFlows(utility::string_t token, boost::optional wabaAccountId) const +pplx::task> FlowsApi::listFlows(utility::string_t token, boost::optional wabaAccountId, boost::optional fields) const { @@ -1058,6 +1081,10 @@ pplx::task> FlowsApi::listFlows(utility: { localVarQueryParams[utility::conversions::to_string_t("wabaAccountId")] = ApiClient::parameterToString(*wabaAccountId); } + if (fields) + { + localVarQueryParams[utility::conversions::to_string_t("fields")] = ApiClient::parameterToString(*fields); + } std::shared_ptr localVarHttpBody; utility::string_t localVarRequestHttpContentType; @@ -1147,9 +1174,15 @@ pplx::task> FlowsApi::listFlows(utility: return localVarResult; }); } -pplx::task> FlowsApi::patchFlowsFlowIdAssets(utility::string_t flowId, utility::string_t token, boost::optional wabaAccountId) const +pplx::task> FlowsApi::patchFlowsFlowIdAssets(utility::string_t flowId, utility::string_t token, std::shared_ptr patchFlowsFlowIdAssetsRequest, boost::optional wabaAccountId) const { + // verify the required parameter 'patchFlowsFlowIdAssetsRequest' is set + if (patchFlowsFlowIdAssetsRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'patchFlowsFlowIdAssetsRequest' when calling FlowsApi->patchFlowsFlowIdAssets")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/flows/{flowId}/assets"); @@ -1188,6 +1221,7 @@ pplx::task> FlowsApi::patch localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); @@ -1204,11 +1238,27 @@ pplx::task> FlowsApi::patch if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(patchFlowsFlowIdAssetsRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } // multipart formdata else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(patchFlowsFlowIdAssetsRequest.get()) + { + patchFlowsFlowIdAssetsRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("patchFlowsFlowIdAssetsRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); } else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) { @@ -1285,9 +1335,15 @@ pplx::task> FlowsApi::patch return localVarResult; }); } -pplx::task>> FlowsApi::patchFlowsFlowIdMetadata(utility::string_t flowId, utility::string_t token, boost::optional wabaAccountId) const +pplx::task>> FlowsApi::patchFlowsFlowIdMetadata(utility::string_t flowId, utility::string_t token, std::shared_ptr patchFlowsFlowIdMetadataRequest, boost::optional wabaAccountId) const { + // verify the required parameter 'patchFlowsFlowIdMetadataRequest' is set + if (patchFlowsFlowIdMetadataRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'patchFlowsFlowIdMetadataRequest' when calling FlowsApi->patchFlowsFlowIdMetadata")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/flows/{flowId}/metadata"); @@ -1326,6 +1382,7 @@ pplx::task>> FlowsApi::patc localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); @@ -1342,11 +1399,27 @@ pplx::task>> FlowsApi::patc if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(patchFlowsFlowIdMetadataRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } // multipart formdata else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(patchFlowsFlowIdMetadataRequest.get()) + { + patchFlowsFlowIdMetadataRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("patchFlowsFlowIdMetadataRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); } else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) { diff --git a/src/api/GroupsApi.cpp b/src/api/GroupsApi.cpp index a286553..8bbdc6f 100644 --- a/src/api/GroupsApi.cpp +++ b/src/api/GroupsApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -35,9 +35,15 @@ GroupsApi::~GroupsApi() { } -pplx::task> GroupsApi::createGroups(utility::string_t token) const +pplx::task> GroupsApi::createGroups(utility::string_t token, std::shared_ptr createGroupsRequest) const { + // verify the required parameter 'createGroupsRequest' is set + if (createGroupsRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'createGroupsRequest' when calling GroupsApi->createGroups")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/groups"); @@ -75,6 +81,7 @@ pplx::task> GroupsApi::createGroups(u localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); @@ -87,11 +94,27 @@ pplx::task> GroupsApi::createGroups(u if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(createGroupsRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } // multipart formdata else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(createGroupsRequest.get()) + { + createGroupsRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("createGroupsRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); } else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) { @@ -168,9 +191,15 @@ pplx::task> GroupsApi::createGroups(u return localVarResult; }); } -pplx::task>> GroupsApi::createGroupsGroupId(utility::string_t groupId, utility::string_t token) const +pplx::task>> GroupsApi::createGroupsGroupId(utility::string_t groupId, utility::string_t token, std::shared_ptr createGroupsGroupIdRequest) const { + // verify the required parameter 'createGroupsGroupIdRequest' is set + if (createGroupsGroupIdRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'createGroupsGroupIdRequest' when calling GroupsApi->createGroupsGroupId")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/groups/{groupId}"); @@ -209,6 +238,7 @@ pplx::task>> GroupsApi::cre localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType; std::unordered_set localVarConsumeHttpContentTypes; + localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); @@ -221,11 +251,27 @@ pplx::task>> GroupsApi::cre if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); + web::json::value localVarJson; + + localVarJson = ModelBase::toJson(createGroupsGroupIdRequest); + + + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } // multipart formdata else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() ) { localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); + std::shared_ptr localVarMultipart(new MultipartFormData); + + if(createGroupsGroupIdRequest.get()) + { + createGroupsGroupIdRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("createGroupsGroupIdRequest")); + } + + + localVarHttpBody = localVarMultipart; + localVarRequestHttpContentType += utility::conversions::to_string_t("; boundary=") + localVarMultipart->getBoundary(); } else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end()) { @@ -580,7 +626,7 @@ pplx::task> GroupsApi::deleteG return localVarResult; }); } -pplx::task>> GroupsApi::getGroupsGroupId(utility::string_t groupId, utility::string_t token) const +pplx::task>> GroupsApi::getGroupsGroupId(utility::string_t groupId, utility::string_t token, boost::optional fields) const { @@ -625,6 +671,10 @@ pplx::task>> GroupsApi::get { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); } + if (fields) + { + localVarQueryParams[utility::conversions::to_string_t("fields")] = ApiClient::parameterToString(*fields); + } std::shared_ptr localVarHttpBody; utility::string_t localVarRequestHttpContentType; @@ -858,7 +908,7 @@ pplx::task>> GroupsApi::get return localVarResult; }); } -pplx::task>> GroupsApi::listGroups(utility::string_t token) const +pplx::task>> GroupsApi::listGroups(utility::string_t token, boost::optional limit, boost::optional before, boost::optional after) const { @@ -902,6 +952,18 @@ pplx::task>> GroupsApi::lis { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); } + if (limit) + { + localVarQueryParams[utility::conversions::to_string_t("limit")] = ApiClient::parameterToString(*limit); + } + if (before) + { + localVarQueryParams[utility::conversions::to_string_t("before")] = ApiClient::parameterToString(*before); + } + if (after) + { + localVarQueryParams[utility::conversions::to_string_t("after")] = ApiClient::parameterToString(*after); + } std::shared_ptr localVarHttpBody; utility::string_t localVarRequestHttpContentType; diff --git a/src/api/MessagingApi.cpp b/src/api/MessagingApi.cpp index c05758f..fddb037 100644 --- a/src/api/MessagingApi.cpp +++ b/src/api/MessagingApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -182,9 +182,15 @@ pplx::task> MessagingApi::create return localVarResult; }); } -pplx::task MessagingApi::createUploadMedia(utility::string_t token, boost::optional>> requestBody) const +pplx::task> MessagingApi::createUploadMedia(utility::string_t token, std::shared_ptr createUploadMediaRequest) const { + // verify the required parameter 'createUploadMediaRequest' is set + if (createUploadMediaRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'createUploadMediaRequest' when calling MessagingApi->createUploadMedia")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/uploadMedia"); @@ -195,6 +201,7 @@ pplx::task MessagingApi::createUploadMedia(utility::string_t token, boost: std::map> localVarFileParams; std::unordered_set localVarResponseHttpContentTypes; + localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("application/json") ); utility::string_t localVarResponseHttpContentType; @@ -236,8 +243,8 @@ pplx::task MessagingApi::createUploadMedia(utility::string_t token, boost: localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); web::json::value localVarJson; - if (requestBody) - localVarJson = ModelBase::toJson(*requestBody); + localVarJson = ModelBase::toJson(createUploadMediaRequest); + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } @@ -247,14 +254,9 @@ pplx::task MessagingApi::createUploadMedia(utility::string_t token, boost: localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); std::shared_ptr localVarMultipart(new MultipartFormData); + if(createUploadMediaRequest.get()) { - std::map localVarJsonMap; - for( auto& localVarItem : requestBody.get() ) - { - web::json::value jval; - localVarJsonMap.insert( std::pair(localVarItem.first, ModelBase::toJson(localVarItem.second) )); - } - localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("requestBody"), localVarJsonMap, utility::conversions::to_string_t("application/json"))); + createUploadMediaRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("createUploadMediaRequest")); } @@ -315,7 +317,25 @@ pplx::task MessagingApi::createUploadMedia(utility::string_t token, boost: }) .then([=, this](utility::string_t localVarResponse) { - return void(); + std::shared_ptr localVarResult(new CreateUploadMedia_200_response()); + + if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) + { + web::json::value localVarJson = web::json::value::parse(localVarResponse); + + ModelBase::fromJson(localVarJson, localVarResult); + } + // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) + // { + // TODO multipart response parsing + // } + else + { + throw ApiException(500 + , utility::conversions::to_string_t("error calling createUploadMedia: unsupported response type")); + } + + return localVarResult; }); } pplx::task> MessagingApi::deleteMedia(utility::string_t token, utility::string_t mediaId) const @@ -741,7 +761,7 @@ pplx::task> MessagingApi::getMmLit return localVarResult; }); } -pplx::task> MessagingApi::listMessages(utility::string_t token) const +pplx::task> MessagingApi::listMessages(utility::string_t token, boost::optional chatId, boost::optional limit, boost::optional last, boost::optional lastMessageNumber, boost::optional firstMessageNumber, boost::optional minTime, boost::optional maxTime, boost::optional msgId) const { @@ -785,6 +805,38 @@ pplx::task> MessagingApi::listMessage { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); } + if (chatId) + { + localVarQueryParams[utility::conversions::to_string_t("chatId")] = ApiClient::parameterToString(*chatId); + } + if (limit) + { + localVarQueryParams[utility::conversions::to_string_t("limit")] = ApiClient::parameterToString(*limit); + } + if (last) + { + localVarQueryParams[utility::conversions::to_string_t("last")] = ApiClient::parameterToString(*last); + } + if (lastMessageNumber) + { + localVarQueryParams[utility::conversions::to_string_t("lastMessageNumber")] = ApiClient::parameterToString(*lastMessageNumber); + } + if (firstMessageNumber) + { + localVarQueryParams[utility::conversions::to_string_t("firstMessageNumber")] = ApiClient::parameterToString(*firstMessageNumber); + } + if (minTime) + { + localVarQueryParams[utility::conversions::to_string_t("min_time")] = ApiClient::parameterToString(*minTime); + } + if (maxTime) + { + localVarQueryParams[utility::conversions::to_string_t("max_time")] = ApiClient::parameterToString(*maxTime); + } + if (msgId) + { + localVarQueryParams[utility::conversions::to_string_t("msgId")] = ApiClient::parameterToString(*msgId); + } std::shared_ptr localVarHttpBody; utility::string_t localVarRequestHttpContentType; @@ -1316,7 +1368,7 @@ pplx::task> MessagingApi::sendButton(utilit return localVarResult; }); } -pplx::task> MessagingApi::sendCarousel(utility::string_t token, std::vector> params, boost::optional body, boost::optional quotedMsgId, boost::optional chatId, boost::optional phone) const +pplx::task> MessagingApi::sendCarousel(utility::string_t token, boost::optional body, boost::optional>>> cards, boost::optional>> params, boost::optional quotedMsgId, boost::optional chatId, boost::optional phone) const { @@ -1362,13 +1414,18 @@ pplx::task> MessagingApi::sendCarousel(util { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); } - { - localVarFormParams[ utility::conversions::to_string_t("params") ] = ApiClient::parameterToString(params); - } if (body) { localVarFormParams[ utility::conversions::to_string_t("body") ] = ApiClient::parameterToString(*body); } + if (cards) + { + localVarFormParams[ utility::conversions::to_string_t("cards") ] = ApiClient::parameterToString(*cards); + } + if (params) + { + localVarFormParams[ utility::conversions::to_string_t("params") ] = ApiClient::parameterToString(*params); + } if (quotedMsgId) { localVarFormParams[ utility::conversions::to_string_t("quotedMsgId") ] = ApiClient::parameterToString(*quotedMsgId); @@ -3061,9 +3118,15 @@ pplx::task> MessagingApi::sendPaymentReques return localVarResult; }); } -pplx::task> MessagingApi::sendProduct(utility::string_t token, boost::optional>> requestBody) const +pplx::task> MessagingApi::sendProduct(utility::string_t token, std::shared_ptr sendProductRequest) const { + // verify the required parameter 'sendProductRequest' is set + if (sendProductRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'sendProductRequest' when calling MessagingApi->sendProduct")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/sendProduct"); @@ -3116,8 +3179,8 @@ pplx::task> MessagingApi::sendProduct(utili localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); web::json::value localVarJson; - if (requestBody) - localVarJson = ModelBase::toJson(*requestBody); + localVarJson = ModelBase::toJson(sendProductRequest); + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } @@ -3127,14 +3190,9 @@ pplx::task> MessagingApi::sendProduct(utili localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); std::shared_ptr localVarMultipart(new MultipartFormData); + if(sendProductRequest.get()) { - std::map localVarJsonMap; - for( auto& localVarItem : requestBody.get() ) - { - web::json::value jval; - localVarJsonMap.insert( std::pair(localVarItem.first, ModelBase::toJson(localVarItem.second) )); - } - localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("requestBody"), localVarJsonMap, utility::conversions::to_string_t("application/json"))); + sendProductRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("sendProductRequest")); } diff --git a/src/api/ProfileApi.cpp b/src/api/ProfileApi.cpp index d078576..8cad5f4 100644 --- a/src/api/ProfileApi.cpp +++ b/src/api/ProfileApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -168,9 +168,15 @@ pplx::task> ProfileApi::getMe(utility::string_t tok return localVarResult; }); } -pplx::task>> ProfileApi::updateMe(utility::string_t token, boost::optional> updateMeRequest) const +pplx::task> ProfileApi::updateMe(utility::string_t token, std::shared_ptr updateMeRequest) const { + // verify the required parameter 'updateMeRequest' is set + if (updateMeRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'updateMeRequest' when calling ProfileApi->updateMe")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/me"); @@ -223,8 +229,8 @@ pplx::task>> ProfileApi::up localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); web::json::value localVarJson; - if (updateMeRequest) - localVarJson = ModelBase::toJson(*updateMeRequest); + localVarJson = ModelBase::toJson(updateMeRequest); + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } @@ -234,9 +240,9 @@ pplx::task>> ProfileApi::up localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); std::shared_ptr localVarMultipart(new MultipartFormData); - if(updateMeRequest && (*updateMeRequest).get()) + if(updateMeRequest.get()) { - (*updateMeRequest)->toMultipart(localVarMultipart, utility::conversions::to_string_t("updateMeRequest")); + updateMeRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("updateMeRequest")); } @@ -297,18 +303,13 @@ pplx::task>> ProfileApi::up }) .then([=, this](utility::string_t localVarResponse) { - std::map> localVarResult; + std::shared_ptr localVarResult(new UpdateMe_200_response()); if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) { web::json::value localVarJson = web::json::value::parse(localVarResponse); - for( auto& localVarItem : localVarJson.as_object() ) - { - std::shared_ptr localVarItemObj; - ModelBase::fromJson(localVarItem.second, localVarItemObj); - localVarResult[localVarItem.first] = localVarItemObj; - } + ModelBase::fromJson(localVarJson, localVarResult); } // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) // { diff --git a/src/api/TemplatesApi.cpp b/src/api/TemplatesApi.cpp index 54591da..1bcd6e8 100644 --- a/src/api/TemplatesApi.cpp +++ b/src/api/TemplatesApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -35,7 +35,7 @@ TemplatesApi::~TemplatesApi() { } -pplx::task>> TemplatesApi::addTemplate(utility::string_t token, boost::optional> addTemplateRequest) const +pplx::task> TemplatesApi::addTemplate(utility::string_t token, boost::optional> addTemplateRequest) const { @@ -164,18 +164,13 @@ pplx::task>> TemplatesApi:: }) .then([=, this](utility::string_t localVarResponse) { - std::map> localVarResult; + std::shared_ptr localVarResult(new AddTemplate_200_response()); if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) { web::json::value localVarJson = web::json::value::parse(localVarResponse); - for( auto& localVarItem : localVarJson.as_object() ) - { - std::shared_ptr localVarItemObj; - ModelBase::fromJson(localVarItem.second, localVarItemObj); - localVarResult[localVarItem.first] = localVarItemObj; - } + ModelBase::fromJson(localVarJson, localVarResult); } // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) // { @@ -190,7 +185,7 @@ pplx::task>> TemplatesApi:: return localVarResult; }); } -pplx::task> TemplatesApi::listTemplates(utility::string_t token) const +pplx::task> TemplatesApi::listTemplates(utility::string_t token, boost::optional limit, boost::optional offset, boost::optional sort) const { @@ -234,6 +229,18 @@ pplx::task> TemplatesApi::listTempla { localVarQueryParams[utility::conversions::to_string_t("token")] = ApiClient::parameterToString(token); } + if (limit) + { + localVarQueryParams[utility::conversions::to_string_t("limit")] = ApiClient::parameterToString(*limit); + } + if (offset) + { + localVarQueryParams[utility::conversions::to_string_t("offset")] = ApiClient::parameterToString(*offset); + } + if (sort) + { + localVarQueryParams[utility::conversions::to_string_t("sort")] = ApiClient::parameterToString(*sort); + } std::shared_ptr localVarHttpBody; utility::string_t localVarRequestHttpContentType; @@ -323,9 +330,15 @@ pplx::task> TemplatesApi::listTempla return localVarResult; }); } -pplx::task>> TemplatesApi::removeTemplate(utility::string_t token, boost::optional>> requestBody) const +pplx::task>> TemplatesApi::removeTemplate(utility::string_t token, std::shared_ptr removeTemplateRequest) const { + // verify the required parameter 'removeTemplateRequest' is set + if (removeTemplateRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'removeTemplateRequest' when calling TemplatesApi->removeTemplate")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/removeTemplate"); @@ -378,8 +391,8 @@ pplx::task>> TemplatesApi:: localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); web::json::value localVarJson; - if (requestBody) - localVarJson = ModelBase::toJson(*requestBody); + localVarJson = ModelBase::toJson(removeTemplateRequest); + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } @@ -389,14 +402,9 @@ pplx::task>> TemplatesApi:: localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); std::shared_ptr localVarMultipart(new MultipartFormData); + if(removeTemplateRequest.get()) { - std::map localVarJsonMap; - for( auto& localVarItem : requestBody.get() ) - { - web::json::value jval; - localVarJsonMap.insert( std::pair(localVarItem.first, ModelBase::toJson(localVarItem.second) )); - } - localVarMultipart->add(ModelBase::toHttpContent(utility::conversions::to_string_t("requestBody"), localVarJsonMap, utility::conversions::to_string_t("application/json"))); + removeTemplateRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("removeTemplateRequest")); } diff --git a/src/api/UsersApi.cpp b/src/api/UsersApi.cpp index 0f336f0..141e9ef 100644 --- a/src/api/UsersApi.cpp +++ b/src/api/UsersApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/api/WebhooksApi.cpp b/src/api/WebhooksApi.cpp index 406d3d4..73bc933 100644 --- a/src/api/WebhooksApi.cpp +++ b/src/api/WebhooksApi.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -168,9 +168,15 @@ pplx::task> WebhooksApi::getWebhook(uti return localVarResult; }); } -pplx::task>> WebhooksApi::setWebhook(utility::string_t token, boost::optional> getWebhook200Response) const +pplx::task> WebhooksApi::setWebhook(utility::string_t token, std::shared_ptr setWebhookRequest) const { + // verify the required parameter 'setWebhookRequest' is set + if (setWebhookRequest == nullptr) + { + throw ApiException(400, utility::conversions::to_string_t("Missing required parameter 'setWebhookRequest' when calling WebhooksApi->setWebhook")); + } + std::shared_ptr localVarApiConfiguration( m_ApiClient->getConfiguration() ); utility::string_t localVarPath = utility::conversions::to_string_t("/webhook"); @@ -223,8 +229,8 @@ pplx::task>> WebhooksApi::s localVarRequestHttpContentType = utility::conversions::to_string_t("application/json"); web::json::value localVarJson; - if (getWebhook200Response) - localVarJson = ModelBase::toJson(*getWebhook200Response); + localVarJson = ModelBase::toJson(setWebhookRequest); + localVarHttpBody = std::shared_ptr( new JsonBody( localVarJson ) ); } @@ -234,9 +240,9 @@ pplx::task>> WebhooksApi::s localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data"); std::shared_ptr localVarMultipart(new MultipartFormData); - if(getWebhook200Response && (*getWebhook200Response).get()) + if(setWebhookRequest.get()) { - (*getWebhook200Response)->toMultipart(localVarMultipart, utility::conversions::to_string_t("getWebhook200Response")); + setWebhookRequest->toMultipart(localVarMultipart, utility::conversions::to_string_t("setWebhookRequest")); } @@ -297,18 +303,13 @@ pplx::task>> WebhooksApi::s }) .then([=, this](utility::string_t localVarResponse) { - std::map> localVarResult; + std::shared_ptr localVarResult(new SetWebhook_200_response()); if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json")) { web::json::value localVarJson = web::json::value::parse(localVarResponse); - for( auto& localVarItem : localVarJson.as_object() ) - { - std::shared_ptr localVarItemObj; - ModelBase::fromJson(localVarItem.second, localVarItemObj); - localVarResult[localVarItem.first] = localVarItemObj; - } + ModelBase::fromJson(localVarJson, localVarResult); } // else if(localVarResponseHttpContentType == utility::conversions::to_string_t("multipart/form-data")) // { diff --git a/src/model/AddTemplate_200_response.cpp b/src/model/AddTemplate_200_response.cpp new file mode 100644 index 0000000..ebcdcd4 --- /dev/null +++ b/src/model/AddTemplate_200_response.cpp @@ -0,0 +1,171 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/AddTemplate_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +AddTemplate_200_response::AddTemplate_200_response() +{ + m_ResponseIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +AddTemplate_200_response::~AddTemplate_200_response() +{ +} + +void AddTemplate_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value AddTemplate_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_ResponseIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("response"))] = ModelBase::toJson(m_Response); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool AddTemplate_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("response")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("response"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setResponse; + ok &= ModelBase::fromJson(fieldValue, refVal_setResponse); + setResponse(refVal_setResponse); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("response"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void AddTemplate_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_ResponseIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("response")), m_Response)); + } +} + +bool AddTemplate_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("response")))) + { + std::map> refVal_setResponse; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("response"))), refVal_setResponse ); + setResponse(refVal_setResponse); + } + return ok; +} + + +std::map> AddTemplate_200_response::getResponse() const +{ + return m_Response; +} + + +void AddTemplate_200_response::setResponse(const std::map>& value) +{ + m_Response = value; + m_ResponseIsSet = true; +} + +bool AddTemplate_200_response::responseIsSet() const +{ + return m_ResponseIsSet; +} + +void AddTemplate_200_response::unsetResponse() +{ + m_ResponseIsSet = false; +} + + +std::map AddTemplate_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void AddTemplate_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void AddTemplate_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool AddTemplate_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void AddTemplate_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/AddTemplate_request.cpp b/src/model/AddTemplate_request.cpp index e9fc309..1ff10f5 100644 --- a/src/model/AddTemplate_request.cpp +++ b/src/model/AddTemplate_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/BlockUser_request.cpp b/src/model/BlockUser_request.cpp index ca34f86..c473b2b 100644 --- a/src/model/BlockUser_request.cpp +++ b/src/model/BlockUser_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings.cpp b/src/model/CallingSettings.cpp index 2dadee2..9cc2556 100644 --- a/src/model/CallingSettings.cpp +++ b/src/model/CallingSettings.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling.cpp b/src/model/CallingSettings_calling.cpp index d07558a..cc6a206 100644 --- a/src/model/CallingSettings_calling.cpp +++ b/src/model/CallingSettings_calling.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling_audio.cpp b/src/model/CallingSettings_calling_audio.cpp index b9cd7ba..3139a97 100644 --- a/src/model/CallingSettings_calling_audio.cpp +++ b/src/model/CallingSettings_calling_audio.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling_call_hours.cpp b/src/model/CallingSettings_calling_call_hours.cpp index c04b42b..23c2d82 100644 --- a/src/model/CallingSettings_calling_call_hours.cpp +++ b/src/model/CallingSettings_calling_call_hours.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling_sip.cpp b/src/model/CallingSettings_calling_sip.cpp index 659b1f9..f31c64a 100644 --- a/src/model/CallingSettings_calling_sip.cpp +++ b/src/model/CallingSettings_calling_sip.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling_sip_servers_inner.cpp b/src/model/CallingSettings_calling_sip_servers_inner.cpp index 6ef58a4..e90d1aa 100644 --- a/src/model/CallingSettings_calling_sip_servers_inner.cpp +++ b/src/model/CallingSettings_calling_sip_servers_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CallingSettings_calling_video.cpp b/src/model/CallingSettings_calling_video.cpp index c69a551..f2e1ffe 100644 --- a/src/model/CallingSettings_calling_video.cpp +++ b/src/model/CallingSettings_calling_video.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ConversationalAutomation.cpp b/src/model/ConversationalAutomation.cpp index a2c36b0..13674bc 100644 --- a/src/model/ConversationalAutomation.cpp +++ b/src/model/ConversationalAutomation.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ConversationalAutomation_commands_inner.cpp b/src/model/ConversationalAutomation_commands_inner.cpp index 95d28dd..9bff28c 100644 --- a/src/model/ConversationalAutomation_commands_inner.cpp +++ b/src/model/ConversationalAutomation_commands_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateCommerce_200_response.cpp b/src/model/CreateCommerce_200_response.cpp index e61da49..7689568 100644 --- a/src/model/CreateCommerce_200_response.cpp +++ b/src/model/CreateCommerce_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateCommerce_request.cpp b/src/model/CreateCommerce_request.cpp index cfa5296..12e0be4 100644 --- a/src/model/CreateCommerce_request.cpp +++ b/src/model/CreateCommerce_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateCommerce_request_params.cpp b/src/model/CreateCommerce_request_params.cpp index c7519e5..5069b57 100644 --- a/src/model/CreateCommerce_request_params.cpp +++ b/src/model/CreateCommerce_request_params.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateFlows_request.cpp b/src/model/CreateFlows_request.cpp new file mode 100644 index 0000000..d42947c --- /dev/null +++ b/src/model/CreateFlows_request.cpp @@ -0,0 +1,398 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateFlows_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateFlows_request::CreateFlows_request() +{ + m_Name = utility::conversions::to_string_t(""); + m_NameIsSet = false; + m_CategoriesIsSet = false; + m_EndpointUri = utility::conversions::to_string_t(""); + m_EndpointUriIsSet = false; + m_Publish = false; + m_PublishIsSet = false; + m_FlowJsonIsSet = false; +} + +CreateFlows_request::~CreateFlows_request() +{ +} + +void CreateFlows_request::validate() +{ + // TODO: implement validation +} + +web::json::value CreateFlows_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_NameIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("name"))] = ModelBase::toJson(m_Name); + } + if(m_CategoriesIsSet) + { + + std::vector refVal = fromCategoriesEnum(m_Categories); + val[utility::conversions::to_string_t(_XPLATSTR("categories"))] = ModelBase::toJson(refVal); + + } + if(m_EndpointUriIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("endpointUri"))] = ModelBase::toJson(m_EndpointUri); + } + if(m_PublishIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("publish"))] = ModelBase::toJson(m_Publish); + } + if(m_FlowJsonIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("flowJson"))] = ModelBase::toJson(m_FlowJson); + } + + return val; +} + +bool CreateFlows_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("name"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromJson(fieldValue, refVal_setName); + setName(refVal_setName); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("categories")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("categories"))); + if(!fieldValue.is_null()) + { + std::vector refVal_setCategories; + ok &= ModelBase::fromJson(fieldValue, refVal_setCategories); + + setCategories(toCategoriesEnum(refVal_setCategories)); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("endpointUri")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("endpointUri"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setEndpointUri; + ok &= ModelBase::fromJson(fieldValue, refVal_setEndpointUri); + setEndpointUri(refVal_setEndpointUri); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("publish")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("publish"))); + if(!fieldValue.is_null()) + { + bool refVal_setPublish; + ok &= ModelBase::fromJson(fieldValue, refVal_setPublish); + setPublish(refVal_setPublish); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("flowJson")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("flowJson"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setFlowJson; + ok &= ModelBase::fromJson(fieldValue, refVal_setFlowJson); + setFlowJson(refVal_setFlowJson); + + } + } + return ok; +} + +void CreateFlows_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_NameIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("name")), m_Name)); + } + if(m_CategoriesIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("categories")), fromCategoriesEnum(m_Categories))); + } + if(m_EndpointUriIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("endpointUri")), m_EndpointUri)); + } + if(m_PublishIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("publish")), m_Publish)); + } + if(m_FlowJsonIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("flowJson")), m_FlowJson)); + } +} + +bool CreateFlows_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("name"))), refVal_setName ); + setName(refVal_setName); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("categories")))) + { + std::vector refVal_setCategories; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("categories"))), refVal_setCategories ); + setCategories(toCategoriesEnum(refVal_setCategories)); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("endpointUri")))) + { + utility::string_t refVal_setEndpointUri; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("endpointUri"))), refVal_setEndpointUri ); + setEndpointUri(refVal_setEndpointUri); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("publish")))) + { + bool refVal_setPublish; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("publish"))), refVal_setPublish ); + setPublish(refVal_setPublish); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("flowJson")))) + { + std::map> refVal_setFlowJson; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("flowJson"))), refVal_setFlowJson ); + setFlowJson(refVal_setFlowJson); + } + return ok; +} + +CreateFlows_request::CategoriesEnum CreateFlows_request::toCategoriesEnum(const utility::string_t& value) const +{ + + if (value == utility::conversions::to_string_t("SIGN_UP")) { + return CategoriesEnum::SIGN_UP; + } + + if (value == utility::conversions::to_string_t("SIGN_IN")) { + return CategoriesEnum::SIGN_IN; + } + + if (value == utility::conversions::to_string_t("APPOINTMENT_BOOKING")) { + return CategoriesEnum::APPOINTMENT_BOOKING; + } + + if (value == utility::conversions::to_string_t("LEAD_GENERATION")) { + return CategoriesEnum::LEAD_GENERATION; + } + + if (value == utility::conversions::to_string_t("CONTACT_US")) { + return CategoriesEnum::CONTACT_US; + } + + if (value == utility::conversions::to_string_t("CUSTOMER_SUPPORT")) { + return CategoriesEnum::CUSTOMER_SUPPORT; + } + + if (value == utility::conversions::to_string_t("SURVEY")) { + return CategoriesEnum::SURVEY; + } + + if (value == utility::conversions::to_string_t("OTHER")) { + return CategoriesEnum::OTHER; + } + + throw std::invalid_argument("Invalid value for conversion to std::vector"); +} + +const utility::string_t CreateFlows_request::fromCategoriesEnum(const CategoriesEnum value) const +{ + switch(value) + { + + case CategoriesEnum::SIGN_UP: return utility::conversions::to_string_t("SIGN_UP"); + + case CategoriesEnum::SIGN_IN: return utility::conversions::to_string_t("SIGN_IN"); + + case CategoriesEnum::APPOINTMENT_BOOKING: return utility::conversions::to_string_t("APPOINTMENT_BOOKING"); + + case CategoriesEnum::LEAD_GENERATION: return utility::conversions::to_string_t("LEAD_GENERATION"); + + case CategoriesEnum::CONTACT_US: return utility::conversions::to_string_t("CONTACT_US"); + + case CategoriesEnum::CUSTOMER_SUPPORT: return utility::conversions::to_string_t("CUSTOMER_SUPPORT"); + + case CategoriesEnum::SURVEY: return utility::conversions::to_string_t("SURVEY"); + + case CategoriesEnum::OTHER: return utility::conversions::to_string_t("OTHER"); + + } +} + +std::vector CreateFlows_request::fromCategoriesEnum(const std::vector& value) const +{ + std::vector ret; + for (auto it = value.begin(); it != value.end(); it++) { + ret.push_back(fromCategoriesEnum(*it)); + } + return ret; +} + +std::vector CreateFlows_request::toCategoriesEnum(const std::vector& value) const +{ + std::vector ret; + for (auto it = value.begin(); it != value.end(); it++) { + ret.push_back(toCategoriesEnum(*it)); + } + return ret; +} + +utility::string_t CreateFlows_request::getName() const +{ + return m_Name; +} + + +void CreateFlows_request::setName(const utility::string_t& value) +{ + m_Name = value; + m_NameIsSet = true; +} + +bool CreateFlows_request::nameIsSet() const +{ + return m_NameIsSet; +} + +void CreateFlows_request::unsetName() +{ + m_NameIsSet = false; +} +std::vector CreateFlows_request::getCategories() const +{ + return m_Categories; +} + + +void CreateFlows_request::setCategories(const std::vector value) +{ + m_Categories = value; + m_CategoriesIsSet = true; +} + +bool CreateFlows_request::categoriesIsSet() const +{ + return m_CategoriesIsSet; +} + +void CreateFlows_request::unsetCategories() +{ + m_CategoriesIsSet = false; +} +utility::string_t CreateFlows_request::getEndpointUri() const +{ + return m_EndpointUri; +} + + +void CreateFlows_request::setEndpointUri(const utility::string_t& value) +{ + m_EndpointUri = value; + m_EndpointUriIsSet = true; +} + +bool CreateFlows_request::endpointUriIsSet() const +{ + return m_EndpointUriIsSet; +} + +void CreateFlows_request::unsetEndpointUri() +{ + m_EndpointUriIsSet = false; +} +bool CreateFlows_request::isPublish() const +{ + return m_Publish; +} + +void CreateFlows_request::setPublish(bool value) +{ + m_Publish = value; + m_PublishIsSet = true; +} + +bool CreateFlows_request::publishIsSet() const +{ + return m_PublishIsSet; +} + +void CreateFlows_request::unsetPublish() +{ + m_PublishIsSet = false; +} +std::map> CreateFlows_request::getFlowJson() const +{ + return m_FlowJson; +} + + +void CreateFlows_request::setFlowJson(const std::map>& value) +{ + m_FlowJson = value; + m_FlowJsonIsSet = true; +} + +bool CreateFlows_request::flowJsonIsSet() const +{ + return m_FlowJsonIsSet; +} + +void CreateFlows_request::unsetFlowJson() +{ + m_FlowJsonIsSet = false; +} + +} +} +} + + diff --git a/src/model/CreateGroupsGroupId_request.cpp b/src/model/CreateGroupsGroupId_request.cpp new file mode 100644 index 0000000..03bc332 --- /dev/null +++ b/src/model/CreateGroupsGroupId_request.cpp @@ -0,0 +1,221 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateGroupsGroupId_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateGroupsGroupId_request::CreateGroupsGroupId_request() +{ + m_Subject = utility::conversions::to_string_t(""); + m_SubjectIsSet = false; + m_Description = utility::conversions::to_string_t(""); + m_DescriptionIsSet = false; + m_Profile_picture_file = utility::conversions::to_string_t(""); + m_Profile_picture_fileIsSet = false; +} + +CreateGroupsGroupId_request::~CreateGroupsGroupId_request() +{ +} + +void CreateGroupsGroupId_request::validate() +{ + // TODO: implement validation +} + +web::json::value CreateGroupsGroupId_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_SubjectIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("subject"))] = ModelBase::toJson(m_Subject); + } + if(m_DescriptionIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("description"))] = ModelBase::toJson(m_Description); + } + if(m_Profile_picture_fileIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("profile_picture_file"))] = ModelBase::toJson(m_Profile_picture_file); + } + + return val; +} + +bool CreateGroupsGroupId_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("subject")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("subject"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setSubject; + ok &= ModelBase::fromJson(fieldValue, refVal_setSubject); + setSubject(refVal_setSubject); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("description")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("description"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setDescription; + ok &= ModelBase::fromJson(fieldValue, refVal_setDescription); + setDescription(refVal_setDescription); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("profile_picture_file")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("profile_picture_file"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setProfilePictureFile; + ok &= ModelBase::fromJson(fieldValue, refVal_setProfilePictureFile); + setProfilePictureFile(refVal_setProfilePictureFile); + + } + } + return ok; +} + +void CreateGroupsGroupId_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_SubjectIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("subject")), m_Subject)); + } + if(m_DescriptionIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("description")), m_Description)); + } + if(m_Profile_picture_fileIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("profile_picture_file")), m_Profile_picture_file)); + } +} + +bool CreateGroupsGroupId_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("subject")))) + { + utility::string_t refVal_setSubject; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("subject"))), refVal_setSubject ); + setSubject(refVal_setSubject); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("description")))) + { + utility::string_t refVal_setDescription; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("description"))), refVal_setDescription ); + setDescription(refVal_setDescription); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("profile_picture_file")))) + { + utility::string_t refVal_setProfilePictureFile; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("profile_picture_file"))), refVal_setProfilePictureFile ); + setProfilePictureFile(refVal_setProfilePictureFile); + } + return ok; +} + + +utility::string_t CreateGroupsGroupId_request::getSubject() const +{ + return m_Subject; +} + + +void CreateGroupsGroupId_request::setSubject(const utility::string_t& value) +{ + m_Subject = value; + m_SubjectIsSet = true; +} + +bool CreateGroupsGroupId_request::subjectIsSet() const +{ + return m_SubjectIsSet; +} + +void CreateGroupsGroupId_request::unsetSubject() +{ + m_SubjectIsSet = false; +} +utility::string_t CreateGroupsGroupId_request::getDescription() const +{ + return m_Description; +} + + +void CreateGroupsGroupId_request::setDescription(const utility::string_t& value) +{ + m_Description = value; + m_DescriptionIsSet = true; +} + +bool CreateGroupsGroupId_request::descriptionIsSet() const +{ + return m_DescriptionIsSet; +} + +void CreateGroupsGroupId_request::unsetDescription() +{ + m_DescriptionIsSet = false; +} +utility::string_t CreateGroupsGroupId_request::getProfilePictureFile() const +{ + return m_Profile_picture_file; +} + + +void CreateGroupsGroupId_request::setProfilePictureFile(const utility::string_t& value) +{ + m_Profile_picture_file = value; + m_Profile_picture_fileIsSet = true; +} + +bool CreateGroupsGroupId_request::profilePictureFileIsSet() const +{ + return m_Profile_picture_fileIsSet; +} + +void CreateGroupsGroupId_request::unsetProfile_picture_file() +{ + m_Profile_picture_fileIsSet = false; +} + +} +} +} + + diff --git a/src/model/CreateGroups_200_response.cpp b/src/model/CreateGroups_200_response.cpp index 74c2fe5..3085cba 100644 --- a/src/model/CreateGroups_200_response.cpp +++ b/src/model/CreateGroups_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateGroups_request.cpp b/src/model/CreateGroups_request.cpp new file mode 100644 index 0000000..672238e --- /dev/null +++ b/src/model/CreateGroups_request.cpp @@ -0,0 +1,172 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateGroups_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateGroups_request::CreateGroups_request() +{ + m_GroupName = utility::conversions::to_string_t(""); + m_GroupNameIsSet = false; + m_Description = utility::conversions::to_string_t(""); + m_DescriptionIsSet = false; +} + +CreateGroups_request::~CreateGroups_request() +{ +} + +void CreateGroups_request::validate() +{ + // TODO: implement validation +} + +web::json::value CreateGroups_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_GroupNameIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("groupName"))] = ModelBase::toJson(m_GroupName); + } + if(m_DescriptionIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("description"))] = ModelBase::toJson(m_Description); + } + + return val; +} + +bool CreateGroups_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("groupName")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("groupName"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setGroupName; + ok &= ModelBase::fromJson(fieldValue, refVal_setGroupName); + setGroupName(refVal_setGroupName); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("description")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("description"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setDescription; + ok &= ModelBase::fromJson(fieldValue, refVal_setDescription); + setDescription(refVal_setDescription); + + } + } + return ok; +} + +void CreateGroups_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_GroupNameIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("groupName")), m_GroupName)); + } + if(m_DescriptionIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("description")), m_Description)); + } +} + +bool CreateGroups_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("groupName")))) + { + utility::string_t refVal_setGroupName; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("groupName"))), refVal_setGroupName ); + setGroupName(refVal_setGroupName); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("description")))) + { + utility::string_t refVal_setDescription; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("description"))), refVal_setDescription ); + setDescription(refVal_setDescription); + } + return ok; +} + + +utility::string_t CreateGroups_request::getGroupName() const +{ + return m_GroupName; +} + + +void CreateGroups_request::setGroupName(const utility::string_t& value) +{ + m_GroupName = value; + m_GroupNameIsSet = true; +} + +bool CreateGroups_request::groupNameIsSet() const +{ + return m_GroupNameIsSet; +} + +void CreateGroups_request::unsetGroupName() +{ + m_GroupNameIsSet = false; +} +utility::string_t CreateGroups_request::getDescription() const +{ + return m_Description; +} + + +void CreateGroups_request::setDescription(const utility::string_t& value) +{ + m_Description = value; + m_DescriptionIsSet = true; +} + +bool CreateGroups_request::descriptionIsSet() const +{ + return m_DescriptionIsSet; +} + +void CreateGroups_request::unsetDescription() +{ + m_DescriptionIsSet = false; +} + +} +} +} + + diff --git a/src/model/CreateReadMessage_200_response.cpp b/src/model/CreateReadMessage_200_response.cpp index c844313..93005e7 100644 --- a/src/model/CreateReadMessage_200_response.cpp +++ b/src/model/CreateReadMessage_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateReadMessage_401_response.cpp b/src/model/CreateReadMessage_401_response.cpp index 4f42c8e..96d9199 100644 --- a/src/model/CreateReadMessage_401_response.cpp +++ b/src/model/CreateReadMessage_401_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateReadMessage_request.cpp b/src/model/CreateReadMessage_request.cpp index bbfa4de..b094ae3 100644 --- a/src/model/CreateReadMessage_request.cpp +++ b/src/model/CreateReadMessage_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/CreateSettings_request.cpp b/src/model/CreateSettings_request.cpp new file mode 100644 index 0000000..5cff9c1 --- /dev/null +++ b/src/model/CreateSettings_request.cpp @@ -0,0 +1,416 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateSettings_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateSettings_request::CreateSettings_request() +{ + m_WebhookUrlIsSet = false; + m_GuaranteedHooks = false; + m_GuaranteedHooksIsSet = false; + m_AckNotificationsOn = false; + m_AckNotificationsOnIsSet = false; + m_RawHooks = false; + m_RawHooksIsSet = false; + m_Template_analytics_enabled = false; + m_Template_analytics_enabledIsSet = false; + m_Cta_url_link_tracking_opted_out = false; + m_Cta_url_link_tracking_opted_outIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +CreateSettings_request::~CreateSettings_request() +{ +} + +void CreateSettings_request::validate() +{ + // TODO: implement validation +} + +web::json::value CreateSettings_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_WebhookUrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl); + } + if(m_GuaranteedHooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))] = ModelBase::toJson(m_GuaranteedHooks); + } + if(m_AckNotificationsOnIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))] = ModelBase::toJson(m_AckNotificationsOn); + } + if(m_RawHooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("rawHooks"))] = ModelBase::toJson(m_RawHooks); + } + if(m_Template_analytics_enabledIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))] = ModelBase::toJson(m_Template_analytics_enabled); + } + if(m_Cta_url_link_tracking_opted_outIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))] = ModelBase::toJson(m_Cta_url_link_tracking_opted_out); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool CreateSettings_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookUrl); + setWebhookUrl(refVal_setWebhookUrl); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setGuaranteedHooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setGuaranteedHooks); + setGuaranteedHooks(refVal_setGuaranteedHooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))); + if(!fieldValue.is_null()) + { + bool refVal_setAckNotificationsOn; + ok &= ModelBase::fromJson(fieldValue, refVal_setAckNotificationsOn); + setAckNotificationsOn(refVal_setAckNotificationsOn); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("rawHooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("rawHooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setRawHooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setRawHooks); + setRawHooks(refVal_setRawHooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))); + if(!fieldValue.is_null()) + { + bool refVal_setTemplateAnalyticsEnabled; + ok &= ModelBase::fromJson(fieldValue, refVal_setTemplateAnalyticsEnabled); + setTemplateAnalyticsEnabled(refVal_setTemplateAnalyticsEnabled); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))); + if(!fieldValue.is_null()) + { + bool refVal_setCtaUrlLinkTrackingOptedOut; + ok &= ModelBase::fromJson(fieldValue, refVal_setCtaUrlLinkTrackingOptedOut); + setCtaUrlLinkTrackingOptedOut(refVal_setCtaUrlLinkTrackingOptedOut); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("rawHooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void CreateSettings_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_WebhookUrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl)); + } + if(m_GuaranteedHooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")), m_GuaranteedHooks)); + } + if(m_AckNotificationsOnIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")), m_AckNotificationsOn)); + } + if(m_RawHooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("rawHooks")), m_RawHooks)); + } + if(m_Template_analytics_enabledIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")), m_Template_analytics_enabled)); + } + if(m_Cta_url_link_tracking_opted_outIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")), m_Cta_url_link_tracking_opted_out)); + } +} + +bool CreateSettings_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))), refVal_setWebhookUrl ); + setWebhookUrl(refVal_setWebhookUrl); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")))) + { + bool refVal_setGuaranteedHooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))), refVal_setGuaranteedHooks ); + setGuaranteedHooks(refVal_setGuaranteedHooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")))) + { + bool refVal_setAckNotificationsOn; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))), refVal_setAckNotificationsOn ); + setAckNotificationsOn(refVal_setAckNotificationsOn); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("rawHooks")))) + { + bool refVal_setRawHooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("rawHooks"))), refVal_setRawHooks ); + setRawHooks(refVal_setRawHooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")))) + { + bool refVal_setTemplateAnalyticsEnabled; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))), refVal_setTemplateAnalyticsEnabled ); + setTemplateAnalyticsEnabled(refVal_setTemplateAnalyticsEnabled); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")))) + { + bool refVal_setCtaUrlLinkTrackingOptedOut; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))), refVal_setCtaUrlLinkTrackingOptedOut ); + setCtaUrlLinkTrackingOptedOut(refVal_setCtaUrlLinkTrackingOptedOut); + } + return ok; +} + + +std::shared_ptr CreateSettings_request::getWebhookUrl() const +{ + return m_WebhookUrl; +} + + +void CreateSettings_request::setWebhookUrl(const std::shared_ptr& value) +{ + m_WebhookUrl = value; + m_WebhookUrlIsSet = true; +} + +bool CreateSettings_request::webhookUrlIsSet() const +{ + return m_WebhookUrlIsSet; +} + +void CreateSettings_request::unsetWebhookUrl() +{ + m_WebhookUrlIsSet = false; +} +bool CreateSettings_request::isGuaranteedHooks() const +{ + return m_GuaranteedHooks; +} + +void CreateSettings_request::setGuaranteedHooks(bool value) +{ + m_GuaranteedHooks = value; + m_GuaranteedHooksIsSet = true; +} + +bool CreateSettings_request::guaranteedHooksIsSet() const +{ + return m_GuaranteedHooksIsSet; +} + +void CreateSettings_request::unsetGuaranteedHooks() +{ + m_GuaranteedHooksIsSet = false; +} +bool CreateSettings_request::isAckNotificationsOn() const +{ + return m_AckNotificationsOn; +} + +void CreateSettings_request::setAckNotificationsOn(bool value) +{ + m_AckNotificationsOn = value; + m_AckNotificationsOnIsSet = true; +} + +bool CreateSettings_request::ackNotificationsOnIsSet() const +{ + return m_AckNotificationsOnIsSet; +} + +void CreateSettings_request::unsetAckNotificationsOn() +{ + m_AckNotificationsOnIsSet = false; +} +bool CreateSettings_request::isRawHooks() const +{ + return m_RawHooks; +} + +void CreateSettings_request::setRawHooks(bool value) +{ + m_RawHooks = value; + m_RawHooksIsSet = true; +} + +bool CreateSettings_request::rawHooksIsSet() const +{ + return m_RawHooksIsSet; +} + +void CreateSettings_request::unsetRawHooks() +{ + m_RawHooksIsSet = false; +} +bool CreateSettings_request::isTemplateAnalyticsEnabled() const +{ + return m_Template_analytics_enabled; +} + +void CreateSettings_request::setTemplateAnalyticsEnabled(bool value) +{ + m_Template_analytics_enabled = value; + m_Template_analytics_enabledIsSet = true; +} + +bool CreateSettings_request::templateAnalyticsEnabledIsSet() const +{ + return m_Template_analytics_enabledIsSet; +} + +void CreateSettings_request::unsetTemplate_analytics_enabled() +{ + m_Template_analytics_enabledIsSet = false; +} +bool CreateSettings_request::isCtaUrlLinkTrackingOptedOut() const +{ + return m_Cta_url_link_tracking_opted_out; +} + +void CreateSettings_request::setCtaUrlLinkTrackingOptedOut(bool value) +{ + m_Cta_url_link_tracking_opted_out = value; + m_Cta_url_link_tracking_opted_outIsSet = true; +} + +bool CreateSettings_request::ctaUrlLinkTrackingOptedOutIsSet() const +{ + return m_Cta_url_link_tracking_opted_outIsSet; +} + +void CreateSettings_request::unsetCta_url_link_tracking_opted_out() +{ + m_Cta_url_link_tracking_opted_outIsSet = false; +} + + +std::map CreateSettings_request::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void CreateSettings_request::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void CreateSettings_request::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool CreateSettings_request::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void CreateSettings_request::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/CreateSettings_request_webhookUrl.cpp b/src/model/CreateSettings_request_webhookUrl.cpp new file mode 100644 index 0000000..27f4716 --- /dev/null +++ b/src/model/CreateSettings_request_webhookUrl.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/CreateSettings_request_webhookUrl.h" diff --git a/src/model/CreateUploadMedia_200_response.cpp b/src/model/CreateUploadMedia_200_response.cpp new file mode 100644 index 0000000..0dd02ff --- /dev/null +++ b/src/model/CreateUploadMedia_200_response.cpp @@ -0,0 +1,172 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateUploadMedia_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateUploadMedia_200_response::CreateUploadMedia_200_response() +{ + m_MediaId = utility::conversions::to_string_t(""); + m_MediaIdIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +CreateUploadMedia_200_response::~CreateUploadMedia_200_response() +{ +} + +void CreateUploadMedia_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value CreateUploadMedia_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_MediaIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("mediaId"))] = ModelBase::toJson(m_MediaId); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool CreateUploadMedia_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("mediaId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("mediaId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setMediaId; + ok &= ModelBase::fromJson(fieldValue, refVal_setMediaId); + setMediaId(refVal_setMediaId); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("mediaId"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void CreateUploadMedia_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_MediaIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("mediaId")), m_MediaId)); + } +} + +bool CreateUploadMedia_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("mediaId")))) + { + utility::string_t refVal_setMediaId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("mediaId"))), refVal_setMediaId ); + setMediaId(refVal_setMediaId); + } + return ok; +} + + +utility::string_t CreateUploadMedia_200_response::getMediaId() const +{ + return m_MediaId; +} + + +void CreateUploadMedia_200_response::setMediaId(const utility::string_t& value) +{ + m_MediaId = value; + m_MediaIdIsSet = true; +} + +bool CreateUploadMedia_200_response::mediaIdIsSet() const +{ + return m_MediaIdIsSet; +} + +void CreateUploadMedia_200_response::unsetMediaId() +{ + m_MediaIdIsSet = false; +} + + +std::map CreateUploadMedia_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void CreateUploadMedia_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void CreateUploadMedia_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool CreateUploadMedia_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void CreateUploadMedia_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/CreateUploadMedia_request.cpp b/src/model/CreateUploadMedia_request.cpp new file mode 100644 index 0000000..e4f91e6 --- /dev/null +++ b/src/model/CreateUploadMedia_request.cpp @@ -0,0 +1,172 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/CreateUploadMedia_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +CreateUploadMedia_request::CreateUploadMedia_request() +{ + m_Body = utility::conversions::to_string_t(""); + m_BodyIsSet = false; + m_Url = utility::conversions::to_string_t(""); + m_UrlIsSet = false; +} + +CreateUploadMedia_request::~CreateUploadMedia_request() +{ +} + +void CreateUploadMedia_request::validate() +{ + // TODO: implement validation +} + +web::json::value CreateUploadMedia_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_BodyIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("body"))] = ModelBase::toJson(m_Body); + } + if(m_UrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("url"))] = ModelBase::toJson(m_Url); + } + + return val; +} + +bool CreateUploadMedia_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setBody; + ok &= ModelBase::fromJson(fieldValue, refVal_setBody); + setBody(refVal_setBody); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("url"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setUrl); + setUrl(refVal_setUrl); + + } + } + return ok; +} + +void CreateUploadMedia_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_BodyIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); + } + if(m_UrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("url")), m_Url)); + } +} + +bool CreateUploadMedia_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) + { + utility::string_t refVal_setBody; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("body"))), refVal_setBody ); + setBody(refVal_setBody); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("url"))), refVal_setUrl ); + setUrl(refVal_setUrl); + } + return ok; +} + + +utility::string_t CreateUploadMedia_request::getBody() const +{ + return m_Body; +} + + +void CreateUploadMedia_request::setBody(const utility::string_t& value) +{ + m_Body = value; + m_BodyIsSet = true; +} + +bool CreateUploadMedia_request::bodyIsSet() const +{ + return m_BodyIsSet; +} + +void CreateUploadMedia_request::unsetBody() +{ + m_BodyIsSet = false; +} +utility::string_t CreateUploadMedia_request::getUrl() const +{ + return m_Url; +} + + +void CreateUploadMedia_request::setUrl(const utility::string_t& value) +{ + m_Url = value; + m_UrlIsSet = true; +} + +bool CreateUploadMedia_request::urlIsSet() const +{ + return m_UrlIsSet; +} + +void CreateUploadMedia_request::unsetUrl() +{ + m_UrlIsSet = false; +} + +} +} +} + + diff --git a/src/model/DeleteFlowsFlowId_200_response.cpp b/src/model/DeleteFlowsFlowId_200_response.cpp index 8491717..fa83ea5 100644 --- a/src/model/DeleteFlowsFlowId_200_response.cpp +++ b/src/model/DeleteFlowsFlowId_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/DeleteGroupsGroupId_200_response.cpp b/src/model/DeleteGroupsGroupId_200_response.cpp index f66bfe2..b8b803d 100644 --- a/src/model/DeleteGroupsGroupId_200_response.cpp +++ b/src/model/DeleteGroupsGroupId_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/DeleteMediaLegacy_request.cpp b/src/model/DeleteMediaLegacy_request.cpp index 05b758f..3bf154e 100644 --- a/src/model/DeleteMediaLegacy_request.cpp +++ b/src/model/DeleteMediaLegacy_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ErrorResponse.cpp b/src/model/ErrorResponse.cpp index 2de817d..684f3e0 100644 --- a/src/model/ErrorResponse.cpp +++ b/src/model/ErrorResponse.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/GetCommerce_200_response_inner.cpp b/src/model/GetCommerce_200_response_inner.cpp index 9221efa..2c55355 100644 --- a/src/model/GetCommerce_200_response_inner.cpp +++ b/src/model/GetCommerce_200_response_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/GetMmLiteStatus_200_response.cpp b/src/model/GetMmLiteStatus_200_response.cpp index 93888e4..f158e6c 100644 --- a/src/model/GetMmLiteStatus_200_response.cpp +++ b/src/model/GetMmLiteStatus_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/GetStatus_200_response.cpp b/src/model/GetStatus_200_response.cpp new file mode 100644 index 0000000..355659a --- /dev/null +++ b/src/model/GetStatus_200_response.cpp @@ -0,0 +1,370 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/GetStatus_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +GetStatus_200_response::GetStatus_200_response() +{ + m_IsCloud = false; + m_IsCloudIsSet = false; + m_Status = utility::conversions::to_string_t(""); + m_StatusIsSet = false; + m_AccountStatus = utility::conversions::to_string_t(""); + m_AccountStatusIsSet = false; + m_Mm_lite_available = false; + m_Mm_lite_availableIsSet = false; + m_Health_status_warning = utility::conversions::to_string_t(""); + m_Health_status_warningIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +GetStatus_200_response::~GetStatus_200_response() +{ +} + +void GetStatus_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value GetStatus_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_IsCloudIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("isCloud"))] = ModelBase::toJson(m_IsCloud); + } + if(m_StatusIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("status"))] = ModelBase::toJson(m_Status); + } + if(m_AccountStatusIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("accountStatus"))] = ModelBase::toJson(m_AccountStatus); + } + if(m_Mm_lite_availableIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("mm_lite_available"))] = ModelBase::toJson(m_Mm_lite_available); + } + if(m_Health_status_warningIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("health_status_warning"))] = ModelBase::toJson(m_Health_status_warning); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool GetStatus_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("isCloud")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("isCloud"))); + if(!fieldValue.is_null()) + { + bool refVal_setIsCloud; + ok &= ModelBase::fromJson(fieldValue, refVal_setIsCloud); + setIsCloud(refVal_setIsCloud); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("status")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("status"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setStatus; + ok &= ModelBase::fromJson(fieldValue, refVal_setStatus); + setStatus(refVal_setStatus); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("accountStatus")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("accountStatus"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setAccountStatus; + ok &= ModelBase::fromJson(fieldValue, refVal_setAccountStatus); + setAccountStatus(refVal_setAccountStatus); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("mm_lite_available")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("mm_lite_available"))); + if(!fieldValue.is_null()) + { + bool refVal_setMmLiteAvailable; + ok &= ModelBase::fromJson(fieldValue, refVal_setMmLiteAvailable); + setMmLiteAvailable(refVal_setMmLiteAvailable); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("health_status_warning")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("health_status_warning"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setHealthStatusWarning; + ok &= ModelBase::fromJson(fieldValue, refVal_setHealthStatusWarning); + setHealthStatusWarning(refVal_setHealthStatusWarning); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("isCloud"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("status"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("accountStatus"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("mm_lite_available"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("health_status_warning"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void GetStatus_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_IsCloudIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("isCloud")), m_IsCloud)); + } + if(m_StatusIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("status")), m_Status)); + } + if(m_AccountStatusIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("accountStatus")), m_AccountStatus)); + } + if(m_Mm_lite_availableIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("mm_lite_available")), m_Mm_lite_available)); + } + if(m_Health_status_warningIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("health_status_warning")), m_Health_status_warning)); + } +} + +bool GetStatus_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("isCloud")))) + { + bool refVal_setIsCloud; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("isCloud"))), refVal_setIsCloud ); + setIsCloud(refVal_setIsCloud); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("status")))) + { + utility::string_t refVal_setStatus; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("status"))), refVal_setStatus ); + setStatus(refVal_setStatus); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("accountStatus")))) + { + utility::string_t refVal_setAccountStatus; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("accountStatus"))), refVal_setAccountStatus ); + setAccountStatus(refVal_setAccountStatus); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("mm_lite_available")))) + { + bool refVal_setMmLiteAvailable; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("mm_lite_available"))), refVal_setMmLiteAvailable ); + setMmLiteAvailable(refVal_setMmLiteAvailable); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("health_status_warning")))) + { + utility::string_t refVal_setHealthStatusWarning; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("health_status_warning"))), refVal_setHealthStatusWarning ); + setHealthStatusWarning(refVal_setHealthStatusWarning); + } + return ok; +} + + +bool GetStatus_200_response::isIsCloud() const +{ + return m_IsCloud; +} + +void GetStatus_200_response::setIsCloud(bool value) +{ + m_IsCloud = value; + m_IsCloudIsSet = true; +} + +bool GetStatus_200_response::isCloudIsSet() const +{ + return m_IsCloudIsSet; +} + +void GetStatus_200_response::unsetIsCloud() +{ + m_IsCloudIsSet = false; +} +utility::string_t GetStatus_200_response::getStatus() const +{ + return m_Status; +} + + +void GetStatus_200_response::setStatus(const utility::string_t& value) +{ + m_Status = value; + m_StatusIsSet = true; +} + +bool GetStatus_200_response::statusIsSet() const +{ + return m_StatusIsSet; +} + +void GetStatus_200_response::unsetStatus() +{ + m_StatusIsSet = false; +} +utility::string_t GetStatus_200_response::getAccountStatus() const +{ + return m_AccountStatus; +} + + +void GetStatus_200_response::setAccountStatus(const utility::string_t& value) +{ + m_AccountStatus = value; + m_AccountStatusIsSet = true; +} + +bool GetStatus_200_response::accountStatusIsSet() const +{ + return m_AccountStatusIsSet; +} + +void GetStatus_200_response::unsetAccountStatus() +{ + m_AccountStatusIsSet = false; +} +bool GetStatus_200_response::isMmLiteAvailable() const +{ + return m_Mm_lite_available; +} + +void GetStatus_200_response::setMmLiteAvailable(bool value) +{ + m_Mm_lite_available = value; + m_Mm_lite_availableIsSet = true; +} + +bool GetStatus_200_response::mmLiteAvailableIsSet() const +{ + return m_Mm_lite_availableIsSet; +} + +void GetStatus_200_response::unsetMm_lite_available() +{ + m_Mm_lite_availableIsSet = false; +} +utility::string_t GetStatus_200_response::getHealthStatusWarning() const +{ + return m_Health_status_warning; +} + + +void GetStatus_200_response::setHealthStatusWarning(const utility::string_t& value) +{ + m_Health_status_warning = value; + m_Health_status_warningIsSet = true; +} + +bool GetStatus_200_response::healthStatusWarningIsSet() const +{ + return m_Health_status_warningIsSet; +} + +void GetStatus_200_response::unsetHealth_status_warning() +{ + m_Health_status_warningIsSet = false; +} + + +std::map GetStatus_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void GetStatus_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void GetStatus_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool GetStatus_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void GetStatus_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/GetWebhook_200_response.cpp b/src/model/GetWebhook_200_response.cpp index 1a5ea15..0226624 100644 --- a/src/model/GetWebhook_200_response.cpp +++ b/src/model/GetWebhook_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -20,8 +20,25 @@ namespace model { GetWebhook_200_response::GetWebhook_200_response() { - m_WebhookUrl = utility::conversions::to_string_t(""); - m_WebhookUrlIsSet = false; + m_HaveDisabledWebhooks = false; + m_HaveDisabledWebhooksIsSet = false; + m_CircuitStateIsSet = false; + m_Reason = utility::conversions::to_string_t(""); + m_ReasonIsSet = false; + m_Fails = 0; + m_FailsIsSet = false; + m_Trips = 0; + m_TripsIsSet = false; + m_DisabledAt = 0; + m_DisabledAtIsSet = false; + m_FirstFailAt = 0; + m_FirstFailAtIsSet = false; + m_LastStatus = 0; + m_LastStatusIsSet = false; + m_NextProbeAt = 0; + m_NextProbeAtIsSet = false; + m_DisabledWebhooksIsSet = false; + m_WebhookStatusesIsSet = false; m_AdditionalPropertiesIsSet = false; } @@ -37,10 +54,67 @@ void GetWebhook_200_response::validate() web::json::value GetWebhook_200_response::toJson() const { web::json::value val = web::json::value::object(); - if(m_WebhookUrlIsSet) + if(m_WebhookUrl.has_value()) { - val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl); + val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl.get()); + } + if(m_HaveDisabledWebhooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))] = ModelBase::toJson(m_HaveDisabledWebhooks); + } + if(m_CircuitStateIsSet) + { + + utility::string_t refVal = fromCircuitStateEnum(m_CircuitState); + val[utility::conversions::to_string_t(_XPLATSTR("circuitState"))] = ModelBase::toJson(refVal); + + } + if(m_ReasonIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("reason"))] = ModelBase::toJson(m_Reason); + } + if(m_FailsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("fails"))] = ModelBase::toJson(m_Fails); + } + if(m_TripsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("trips"))] = ModelBase::toJson(m_Trips); + } + if(m_DisabledAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("disabledAt"))] = ModelBase::toJson(m_DisabledAt); + } + if(m_FirstFailAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))] = ModelBase::toJson(m_FirstFailAt); + } + if(m_LastStatusIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("lastStatus"))] = ModelBase::toJson(m_LastStatus); + } + if(m_NextProbeAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))] = ModelBase::toJson(m_NextProbeAt); + } + if(m_DisabledWebhooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))] = ModelBase::toJson(m_DisabledWebhooks); + } + if(m_WebhookStatusesIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))] = ModelBase::toJson(m_WebhookStatuses); } // Serialize additional properties if(m_AdditionalPropertiesIsSet) @@ -62,12 +136,134 @@ bool GetWebhook_200_response::fromJson(const web::json::value& val) const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))); if(!fieldValue.is_null()) { - utility::string_t refVal_setWebhookUrl; + std::shared_ptr refVal_setWebhookUrl; ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookUrl); setWebhookUrl(refVal_setWebhookUrl); } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setHaveDisabledWebhooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setHaveDisabledWebhooks); + setHaveDisabledWebhooks(refVal_setHaveDisabledWebhooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("circuitState"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromJson(fieldValue, refVal_setCircuitState); + + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("reason"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromJson(fieldValue, refVal_setReason); + setReason(refVal_setReason); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("fails"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFails; + ok &= ModelBase::fromJson(fieldValue, refVal_setFails); + setFails(refVal_setFails); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("trips"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromJson(fieldValue, refVal_setTrips); + setTrips(refVal_setTrips); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setDisabledAt); + setDisabledAt(refVal_setDisabledAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setFirstFailAt); + setFirstFailAt(refVal_setFirstFailAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromJson(fieldValue, refVal_setLastStatus); + setLastStatus(refVal_setLastStatus); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setNextProbeAt); + setNextProbeAt(refVal_setNextProbeAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))); + if(!fieldValue.is_null()) + { + std::vector>> refVal_setDisabledWebhooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setDisabledWebhooks); + setDisabledWebhooks(refVal_setDisabledWebhooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))); + if(!fieldValue.is_null()) + { + std::vector> refVal_setWebhookStatuses; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookStatuses); + setWebhookStatuses(refVal_setWebhookStatuses); + + } + } // Capture additional properties (keys not defined in the schema) if(val.is_object()) { @@ -75,6 +271,17 @@ bool GetWebhook_200_response::fromJson(const web::json::value& val) { // Skip known properties if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("circuitState"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("reason"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("fails"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("trips"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("disabledAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("lastStatus"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))) continue; // This is an additional property m_AdditionalProperties[item.first] = item.second; m_AdditionalPropertiesIsSet = true; @@ -90,9 +297,53 @@ void GetWebhook_200_response::toMultipart(std::shared_ptr mul { namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); } - if(m_WebhookUrlIsSet) + if(m_WebhookUrl.has_value()) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl.get())); + } + if(m_HaveDisabledWebhooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")), m_HaveDisabledWebhooks)); + } + if(m_CircuitStateIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("circuitState")), fromCircuitStateEnum(m_CircuitState))); + } + if(m_ReasonIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("reason")), m_Reason)); + } + if(m_FailsIsSet) { - multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl)); + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("fails")), m_Fails)); + } + if(m_TripsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("trips")), m_Trips)); + } + if(m_DisabledAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("disabledAt")), m_DisabledAt)); + } + if(m_FirstFailAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("firstFailAt")), m_FirstFailAt)); + } + if(m_LastStatusIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("lastStatus")), m_LastStatus)); + } + if(m_NextProbeAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")), m_NextProbeAt)); + } + if(m_DisabledWebhooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")), m_DisabledWebhooks)); + } + if(m_WebhookStatusesIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")), m_WebhookStatuses)); } } @@ -107,34 +358,368 @@ bool GetWebhook_200_response::fromMultiPart(std::shared_ptr m if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) { - utility::string_t refVal_setWebhookUrl; + std::shared_ptr refVal_setWebhookUrl; ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))), refVal_setWebhookUrl ); setWebhookUrl(refVal_setWebhookUrl); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")))) + { + bool refVal_setHaveDisabledWebhooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))), refVal_setHaveDisabledWebhooks ); + setHaveDisabledWebhooks(refVal_setHaveDisabledWebhooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("circuitState"))), refVal_setCircuitState ); + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("reason"))), refVal_setReason ); + setReason(refVal_setReason); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + int32_t refVal_setFails; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("fails"))), refVal_setFails ); + setFails(refVal_setFails); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("trips"))), refVal_setTrips ); + setTrips(refVal_setTrips); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))), refVal_setDisabledAt ); + setDisabledAt(refVal_setDisabledAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))), refVal_setFirstFailAt ); + setFirstFailAt(refVal_setFirstFailAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))), refVal_setLastStatus ); + setLastStatus(refVal_setLastStatus); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))), refVal_setNextProbeAt ); + setNextProbeAt(refVal_setNextProbeAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")))) + { + std::vector>> refVal_setDisabledWebhooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))), refVal_setDisabledWebhooks ); + setDisabledWebhooks(refVal_setDisabledWebhooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")))) + { + std::vector> refVal_setWebhookStatuses; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))), refVal_setWebhookStatuses ); + setWebhookStatuses(refVal_setWebhookStatuses); + } return ok; } +GetWebhook_200_response::CircuitStateEnum GetWebhook_200_response::toCircuitStateEnum(const utility::string_t& value) const +{ + + if (value == utility::conversions::to_string_t("ok")) { + return CircuitStateEnum::OK; + } + + if (value == utility::conversions::to_string_t("degraded")) { + return CircuitStateEnum::DEGRADED; + } + + if (value == utility::conversions::to_string_t("open")) { + return CircuitStateEnum::OPEN; + } + + if (value == utility::conversions::to_string_t("half_open")) { + return CircuitStateEnum::HALF_OPEN; + } + + if (value == utility::conversions::to_string_t("disabled")) { + return CircuitStateEnum::DISABLED; + } + + throw std::invalid_argument("Invalid value for conversion to CircuitStateEnum"); +} + -utility::string_t GetWebhook_200_response::getWebhookUrl() const +const utility::string_t GetWebhook_200_response::fromCircuitStateEnum(const CircuitStateEnum value) const { - return m_WebhookUrl; + switch(value) + { + + case CircuitStateEnum::OK: return utility::conversions::to_string_t("ok"); + + case CircuitStateEnum::DEGRADED: return utility::conversions::to_string_t("degraded"); + + case CircuitStateEnum::OPEN: return utility::conversions::to_string_t("open"); + + case CircuitStateEnum::HALF_OPEN: return utility::conversions::to_string_t("half_open"); + + case CircuitStateEnum::DISABLED: return utility::conversions::to_string_t("disabled"); + + } } -void GetWebhook_200_response::setWebhookUrl(const utility::string_t& value) +std::shared_ptr GetWebhook_200_response::getWebhookUrl() const +{ + return m_WebhookUrl.get(); +} + + +void GetWebhook_200_response::setWebhookUrl(const std::shared_ptr& value) { m_WebhookUrl = value; - m_WebhookUrlIsSet = true; } bool GetWebhook_200_response::webhookUrlIsSet() const { - return m_WebhookUrlIsSet; + return m_WebhookUrl.has_value(); } void GetWebhook_200_response::unsetWebhookUrl() { - m_WebhookUrlIsSet = false; + m_WebhookUrl.reset(); +} +bool GetWebhook_200_response::isHaveDisabledWebhooks() const +{ + return m_HaveDisabledWebhooks; +} + +void GetWebhook_200_response::setHaveDisabledWebhooks(bool value) +{ + m_HaveDisabledWebhooks = value; + m_HaveDisabledWebhooksIsSet = true; +} + +bool GetWebhook_200_response::haveDisabledWebhooksIsSet() const +{ + return m_HaveDisabledWebhooksIsSet; +} + +void GetWebhook_200_response::unsetHaveDisabledWebhooks() +{ + m_HaveDisabledWebhooksIsSet = false; +} +GetWebhook_200_response::CircuitStateEnum GetWebhook_200_response::getCircuitState() const +{ + return m_CircuitState; +} + + +void GetWebhook_200_response::setCircuitState(const CircuitStateEnum value) +{ + m_CircuitState = value; + m_CircuitStateIsSet = true; +} + +bool GetWebhook_200_response::circuitStateIsSet() const +{ + return m_CircuitStateIsSet; +} + +void GetWebhook_200_response::unsetCircuitState() +{ + m_CircuitStateIsSet = false; +} +utility::string_t GetWebhook_200_response::getReason() const +{ + return m_Reason; +} + + +void GetWebhook_200_response::setReason(const utility::string_t& value) +{ + m_Reason = value; + m_ReasonIsSet = true; +} + +bool GetWebhook_200_response::reasonIsSet() const +{ + return m_ReasonIsSet; +} + +void GetWebhook_200_response::unsetReason() +{ + m_ReasonIsSet = false; +} +int32_t GetWebhook_200_response::getFails() const +{ + return m_Fails; +} + +void GetWebhook_200_response::setFails(int32_t value) +{ + m_Fails = value; + m_FailsIsSet = true; +} + +bool GetWebhook_200_response::failsIsSet() const +{ + return m_FailsIsSet; +} + +void GetWebhook_200_response::unsetFails() +{ + m_FailsIsSet = false; +} +int32_t GetWebhook_200_response::getTrips() const +{ + return m_Trips; +} + +void GetWebhook_200_response::setTrips(int32_t value) +{ + m_Trips = value; + m_TripsIsSet = true; +} + +bool GetWebhook_200_response::tripsIsSet() const +{ + return m_TripsIsSet; +} + +void GetWebhook_200_response::unsetTrips() +{ + m_TripsIsSet = false; +} +int32_t GetWebhook_200_response::getDisabledAt() const +{ + return m_DisabledAt; +} + +void GetWebhook_200_response::setDisabledAt(int32_t value) +{ + m_DisabledAt = value; + m_DisabledAtIsSet = true; +} + +bool GetWebhook_200_response::disabledAtIsSet() const +{ + return m_DisabledAtIsSet; +} + +void GetWebhook_200_response::unsetDisabledAt() +{ + m_DisabledAtIsSet = false; +} +int32_t GetWebhook_200_response::getFirstFailAt() const +{ + return m_FirstFailAt; +} + +void GetWebhook_200_response::setFirstFailAt(int32_t value) +{ + m_FirstFailAt = value; + m_FirstFailAtIsSet = true; +} + +bool GetWebhook_200_response::firstFailAtIsSet() const +{ + return m_FirstFailAtIsSet; +} + +void GetWebhook_200_response::unsetFirstFailAt() +{ + m_FirstFailAtIsSet = false; +} +int32_t GetWebhook_200_response::getLastStatus() const +{ + return m_LastStatus; +} + +void GetWebhook_200_response::setLastStatus(int32_t value) +{ + m_LastStatus = value; + m_LastStatusIsSet = true; +} + +bool GetWebhook_200_response::lastStatusIsSet() const +{ + return m_LastStatusIsSet; +} + +void GetWebhook_200_response::unsetLastStatus() +{ + m_LastStatusIsSet = false; +} +int32_t GetWebhook_200_response::getNextProbeAt() const +{ + return m_NextProbeAt; +} + +void GetWebhook_200_response::setNextProbeAt(int32_t value) +{ + m_NextProbeAt = value; + m_NextProbeAtIsSet = true; +} + +bool GetWebhook_200_response::nextProbeAtIsSet() const +{ + return m_NextProbeAtIsSet; +} + +void GetWebhook_200_response::unsetNextProbeAt() +{ + m_NextProbeAtIsSet = false; +} +std::vector>> GetWebhook_200_response::getDisabledWebhooks() const +{ + return m_DisabledWebhooks; +} + + +void GetWebhook_200_response::setDisabledWebhooks(const std::vector>>& value) +{ + m_DisabledWebhooks = value; + m_DisabledWebhooksIsSet = true; +} + +bool GetWebhook_200_response::disabledWebhooksIsSet() const +{ + return m_DisabledWebhooksIsSet; +} + +void GetWebhook_200_response::unsetDisabledWebhooks() +{ + m_DisabledWebhooksIsSet = false; +} +std::vector> GetWebhook_200_response::getWebhookStatuses() const +{ + return m_WebhookStatuses; +} + + +void GetWebhook_200_response::setWebhookStatuses(const std::vector>& value) +{ + m_WebhookStatuses = value; + m_WebhookStatusesIsSet = true; +} + +bool GetWebhook_200_response::webhookStatusesIsSet() const +{ + return m_WebhookStatusesIsSet; +} + +void GetWebhook_200_response::unsetWebhookStatuses() +{ + m_WebhookStatusesIsSet = false; } diff --git a/src/model/GetWebhook_200_response_webhookUrl.cpp b/src/model/GetWebhook_200_response_webhookUrl.cpp new file mode 100644 index 0000000..e402ef1 --- /dev/null +++ b/src/model/GetWebhook_200_response_webhookUrl.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/GetWebhook_200_response_webhookUrl.h" diff --git a/src/model/GetWhatsappBusinessEncryption_200_response.cpp b/src/model/GetWhatsappBusinessEncryption_200_response.cpp index cf09030..b1a2263 100644 --- a/src/model/GetWhatsappBusinessEncryption_200_response.cpp +++ b/src/model/GetWhatsappBusinessEncryption_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/InitiateCallRequest.cpp b/src/model/InitiateCallRequest.cpp index 84f7338..2b44539 100644 --- a/src/model/InitiateCallRequest.cpp +++ b/src/model/InitiateCallRequest.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/InitiateCallRequest_session.cpp b/src/model/InitiateCallRequest_session.cpp index b4448db..22bcd19 100644 --- a/src/model/InitiateCallRequest_session.cpp +++ b/src/model/InitiateCallRequest_session.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/InitiateCallResponse.cpp b/src/model/InitiateCallResponse.cpp index ee75049..deda9e9 100644 --- a/src/model/InitiateCallResponse.cpp +++ b/src/model/InitiateCallResponse.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/InitiateCallResponse_calls_inner.cpp b/src/model/InitiateCallResponse_calls_inner.cpp index 5f61cb2..1982910 100644 --- a/src/model/InitiateCallResponse_calls_inner.cpp +++ b/src/model/InitiateCallResponse_calls_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/InitiateCallResponse_response.cpp b/src/model/InitiateCallResponse_response.cpp index 0d5c2bb..41be63d 100644 --- a/src/model/InitiateCallResponse_response.cpp +++ b/src/model/InitiateCallResponse_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ListBlockedUsers_200_response.cpp b/src/model/ListBlockedUsers_200_response.cpp index ad6fe46..d26bd2f 100644 --- a/src/model/ListBlockedUsers_200_response.cpp +++ b/src/model/ListBlockedUsers_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ListFlows_200_response.cpp b/src/model/ListFlows_200_response.cpp index 1783e8e..9e6110f 100644 --- a/src/model/ListFlows_200_response.cpp +++ b/src/model/ListFlows_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ListMessages_200_response.cpp b/src/model/ListMessages_200_response.cpp index b30edaa..14d74f2 100644 --- a/src/model/ListMessages_200_response.cpp +++ b/src/model/ListMessages_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/ListSettings_200_response.cpp b/src/model/ListSettings_200_response.cpp new file mode 100644 index 0000000..ee0d89a --- /dev/null +++ b/src/model/ListSettings_200_response.cpp @@ -0,0 +1,1053 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/ListSettings_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +ListSettings_200_response::ListSettings_200_response() +{ + m_WebhookUrlIsSet = false; + m_GuaranteedHooks = false; + m_GuaranteedHooksIsSet = false; + m_AckNotificationsOn = false; + m_AckNotificationsOnIsSet = false; + m_RawHooks = false; + m_RawHooksIsSet = false; + m_Mm_lite_enabled = false; + m_Mm_lite_enabledIsSet = false; + m_Template_analytics_enabled = false; + m_Template_analytics_enabledIsSet = false; + m_Cta_url_link_tracking_opted_out = false; + m_Cta_url_link_tracking_opted_outIsSet = false; + m_HaveDisabledWebhooks = false; + m_HaveDisabledWebhooksIsSet = false; + m_CircuitStateIsSet = false; + m_Reason = utility::conversions::to_string_t(""); + m_ReasonIsSet = false; + m_Fails = 0; + m_FailsIsSet = false; + m_Trips = 0; + m_TripsIsSet = false; + m_DisabledAt = 0; + m_DisabledAtIsSet = false; + m_FirstFailAt = 0; + m_FirstFailAtIsSet = false; + m_LastStatus = 0; + m_LastStatusIsSet = false; + m_NextProbeAt = 0; + m_NextProbeAtIsSet = false; + m_DisabledWebhooksIsSet = false; + m_WebhookStatusesIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +ListSettings_200_response::~ListSettings_200_response() +{ +} + +void ListSettings_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value ListSettings_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_WebhookUrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl); + } + if(m_GuaranteedHooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))] = ModelBase::toJson(m_GuaranteedHooks); + } + if(m_AckNotificationsOnIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))] = ModelBase::toJson(m_AckNotificationsOn); + } + if(m_RawHooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("rawHooks"))] = ModelBase::toJson(m_RawHooks); + } + if(m_Mm_lite_enabledIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled"))] = ModelBase::toJson(m_Mm_lite_enabled); + } + if(m_Template_analytics_enabledIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))] = ModelBase::toJson(m_Template_analytics_enabled); + } + if(m_Cta_url_link_tracking_opted_outIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))] = ModelBase::toJson(m_Cta_url_link_tracking_opted_out); + } + if(m_HaveDisabledWebhooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))] = ModelBase::toJson(m_HaveDisabledWebhooks); + } + if(m_CircuitStateIsSet) + { + + utility::string_t refVal = fromCircuitStateEnum(m_CircuitState); + val[utility::conversions::to_string_t(_XPLATSTR("circuitState"))] = ModelBase::toJson(refVal); + + } + if(m_ReasonIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("reason"))] = ModelBase::toJson(m_Reason); + } + if(m_FailsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("fails"))] = ModelBase::toJson(m_Fails); + } + if(m_TripsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("trips"))] = ModelBase::toJson(m_Trips); + } + if(m_DisabledAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("disabledAt"))] = ModelBase::toJson(m_DisabledAt); + } + if(m_FirstFailAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))] = ModelBase::toJson(m_FirstFailAt); + } + if(m_LastStatusIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("lastStatus"))] = ModelBase::toJson(m_LastStatus); + } + if(m_NextProbeAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))] = ModelBase::toJson(m_NextProbeAt); + } + if(m_DisabledWebhooksIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))] = ModelBase::toJson(m_DisabledWebhooks); + } + if(m_WebhookStatusesIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))] = ModelBase::toJson(m_WebhookStatuses); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool ListSettings_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookUrl); + setWebhookUrl(refVal_setWebhookUrl); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setGuaranteedHooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setGuaranteedHooks); + setGuaranteedHooks(refVal_setGuaranteedHooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))); + if(!fieldValue.is_null()) + { + bool refVal_setAckNotificationsOn; + ok &= ModelBase::fromJson(fieldValue, refVal_setAckNotificationsOn); + setAckNotificationsOn(refVal_setAckNotificationsOn); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("rawHooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("rawHooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setRawHooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setRawHooks); + setRawHooks(refVal_setRawHooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled"))); + if(!fieldValue.is_null()) + { + bool refVal_setMmLiteEnabled; + ok &= ModelBase::fromJson(fieldValue, refVal_setMmLiteEnabled); + setMmLiteEnabled(refVal_setMmLiteEnabled); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))); + if(!fieldValue.is_null()) + { + bool refVal_setTemplateAnalyticsEnabled; + ok &= ModelBase::fromJson(fieldValue, refVal_setTemplateAnalyticsEnabled); + setTemplateAnalyticsEnabled(refVal_setTemplateAnalyticsEnabled); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))); + if(!fieldValue.is_null()) + { + bool refVal_setCtaUrlLinkTrackingOptedOut; + ok &= ModelBase::fromJson(fieldValue, refVal_setCtaUrlLinkTrackingOptedOut); + setCtaUrlLinkTrackingOptedOut(refVal_setCtaUrlLinkTrackingOptedOut); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))); + if(!fieldValue.is_null()) + { + bool refVal_setHaveDisabledWebhooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setHaveDisabledWebhooks); + setHaveDisabledWebhooks(refVal_setHaveDisabledWebhooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("circuitState"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromJson(fieldValue, refVal_setCircuitState); + + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("reason"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromJson(fieldValue, refVal_setReason); + setReason(refVal_setReason); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("fails"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFails; + ok &= ModelBase::fromJson(fieldValue, refVal_setFails); + setFails(refVal_setFails); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("trips"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromJson(fieldValue, refVal_setTrips); + setTrips(refVal_setTrips); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setDisabledAt); + setDisabledAt(refVal_setDisabledAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setFirstFailAt); + setFirstFailAt(refVal_setFirstFailAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromJson(fieldValue, refVal_setLastStatus); + setLastStatus(refVal_setLastStatus); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setNextProbeAt); + setNextProbeAt(refVal_setNextProbeAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))); + if(!fieldValue.is_null()) + { + std::vector>> refVal_setDisabledWebhooks; + ok &= ModelBase::fromJson(fieldValue, refVal_setDisabledWebhooks); + setDisabledWebhooks(refVal_setDisabledWebhooks); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))); + if(!fieldValue.is_null()) + { + std::vector> refVal_setWebhookStatuses; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookStatuses); + setWebhookStatuses(refVal_setWebhookStatuses); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("rawHooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("circuitState"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("reason"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("fails"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("trips"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("disabledAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("lastStatus"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void ListSettings_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_WebhookUrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl)); + } + if(m_GuaranteedHooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")), m_GuaranteedHooks)); + } + if(m_AckNotificationsOnIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")), m_AckNotificationsOn)); + } + if(m_RawHooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("rawHooks")), m_RawHooks)); + } + if(m_Mm_lite_enabledIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled")), m_Mm_lite_enabled)); + } + if(m_Template_analytics_enabledIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")), m_Template_analytics_enabled)); + } + if(m_Cta_url_link_tracking_opted_outIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")), m_Cta_url_link_tracking_opted_out)); + } + if(m_HaveDisabledWebhooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")), m_HaveDisabledWebhooks)); + } + if(m_CircuitStateIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("circuitState")), fromCircuitStateEnum(m_CircuitState))); + } + if(m_ReasonIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("reason")), m_Reason)); + } + if(m_FailsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("fails")), m_Fails)); + } + if(m_TripsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("trips")), m_Trips)); + } + if(m_DisabledAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("disabledAt")), m_DisabledAt)); + } + if(m_FirstFailAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("firstFailAt")), m_FirstFailAt)); + } + if(m_LastStatusIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("lastStatus")), m_LastStatus)); + } + if(m_NextProbeAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")), m_NextProbeAt)); + } + if(m_DisabledWebhooksIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")), m_DisabledWebhooks)); + } + if(m_WebhookStatusesIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")), m_WebhookStatuses)); + } +} + +bool ListSettings_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))), refVal_setWebhookUrl ); + setWebhookUrl(refVal_setWebhookUrl); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks")))) + { + bool refVal_setGuaranteedHooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("guaranteedHooks"))), refVal_setGuaranteedHooks ); + setGuaranteedHooks(refVal_setGuaranteedHooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn")))) + { + bool refVal_setAckNotificationsOn; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("ackNotificationsOn"))), refVal_setAckNotificationsOn ); + setAckNotificationsOn(refVal_setAckNotificationsOn); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("rawHooks")))) + { + bool refVal_setRawHooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("rawHooks"))), refVal_setRawHooks ); + setRawHooks(refVal_setRawHooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled")))) + { + bool refVal_setMmLiteEnabled; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("mm_lite_enabled"))), refVal_setMmLiteEnabled ); + setMmLiteEnabled(refVal_setMmLiteEnabled); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled")))) + { + bool refVal_setTemplateAnalyticsEnabled; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("template_analytics_enabled"))), refVal_setTemplateAnalyticsEnabled ); + setTemplateAnalyticsEnabled(refVal_setTemplateAnalyticsEnabled); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out")))) + { + bool refVal_setCtaUrlLinkTrackingOptedOut; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("cta_url_link_tracking_opted_out"))), refVal_setCtaUrlLinkTrackingOptedOut ); + setCtaUrlLinkTrackingOptedOut(refVal_setCtaUrlLinkTrackingOptedOut); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks")))) + { + bool refVal_setHaveDisabledWebhooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("haveDisabledWebhooks"))), refVal_setHaveDisabledWebhooks ); + setHaveDisabledWebhooks(refVal_setHaveDisabledWebhooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("circuitState"))), refVal_setCircuitState ); + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("reason"))), refVal_setReason ); + setReason(refVal_setReason); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + int32_t refVal_setFails; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("fails"))), refVal_setFails ); + setFails(refVal_setFails); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("trips"))), refVal_setTrips ); + setTrips(refVal_setTrips); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))), refVal_setDisabledAt ); + setDisabledAt(refVal_setDisabledAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))), refVal_setFirstFailAt ); + setFirstFailAt(refVal_setFirstFailAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))), refVal_setLastStatus ); + setLastStatus(refVal_setLastStatus); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))), refVal_setNextProbeAt ); + setNextProbeAt(refVal_setNextProbeAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks")))) + { + std::vector>> refVal_setDisabledWebhooks; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("disabledWebhooks"))), refVal_setDisabledWebhooks ); + setDisabledWebhooks(refVal_setDisabledWebhooks); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses")))) + { + std::vector> refVal_setWebhookStatuses; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookStatuses"))), refVal_setWebhookStatuses ); + setWebhookStatuses(refVal_setWebhookStatuses); + } + return ok; +} + +ListSettings_200_response::CircuitStateEnum ListSettings_200_response::toCircuitStateEnum(const utility::string_t& value) const +{ + + if (value == utility::conversions::to_string_t("ok")) { + return CircuitStateEnum::OK; + } + + if (value == utility::conversions::to_string_t("degraded")) { + return CircuitStateEnum::DEGRADED; + } + + if (value == utility::conversions::to_string_t("open")) { + return CircuitStateEnum::OPEN; + } + + if (value == utility::conversions::to_string_t("half_open")) { + return CircuitStateEnum::HALF_OPEN; + } + + if (value == utility::conversions::to_string_t("disabled")) { + return CircuitStateEnum::DISABLED; + } + + throw std::invalid_argument("Invalid value for conversion to CircuitStateEnum"); +} + + +const utility::string_t ListSettings_200_response::fromCircuitStateEnum(const CircuitStateEnum value) const +{ + switch(value) + { + + case CircuitStateEnum::OK: return utility::conversions::to_string_t("ok"); + + case CircuitStateEnum::DEGRADED: return utility::conversions::to_string_t("degraded"); + + case CircuitStateEnum::OPEN: return utility::conversions::to_string_t("open"); + + case CircuitStateEnum::HALF_OPEN: return utility::conversions::to_string_t("half_open"); + + case CircuitStateEnum::DISABLED: return utility::conversions::to_string_t("disabled"); + + } +} + + +std::shared_ptr ListSettings_200_response::getWebhookUrl() const +{ + return m_WebhookUrl; +} + + +void ListSettings_200_response::setWebhookUrl(const std::shared_ptr& value) +{ + m_WebhookUrl = value; + m_WebhookUrlIsSet = true; +} + +bool ListSettings_200_response::webhookUrlIsSet() const +{ + return m_WebhookUrlIsSet; +} + +void ListSettings_200_response::unsetWebhookUrl() +{ + m_WebhookUrlIsSet = false; +} +bool ListSettings_200_response::isGuaranteedHooks() const +{ + return m_GuaranteedHooks; +} + +void ListSettings_200_response::setGuaranteedHooks(bool value) +{ + m_GuaranteedHooks = value; + m_GuaranteedHooksIsSet = true; +} + +bool ListSettings_200_response::guaranteedHooksIsSet() const +{ + return m_GuaranteedHooksIsSet; +} + +void ListSettings_200_response::unsetGuaranteedHooks() +{ + m_GuaranteedHooksIsSet = false; +} +bool ListSettings_200_response::isAckNotificationsOn() const +{ + return m_AckNotificationsOn; +} + +void ListSettings_200_response::setAckNotificationsOn(bool value) +{ + m_AckNotificationsOn = value; + m_AckNotificationsOnIsSet = true; +} + +bool ListSettings_200_response::ackNotificationsOnIsSet() const +{ + return m_AckNotificationsOnIsSet; +} + +void ListSettings_200_response::unsetAckNotificationsOn() +{ + m_AckNotificationsOnIsSet = false; +} +bool ListSettings_200_response::isRawHooks() const +{ + return m_RawHooks; +} + +void ListSettings_200_response::setRawHooks(bool value) +{ + m_RawHooks = value; + m_RawHooksIsSet = true; +} + +bool ListSettings_200_response::rawHooksIsSet() const +{ + return m_RawHooksIsSet; +} + +void ListSettings_200_response::unsetRawHooks() +{ + m_RawHooksIsSet = false; +} +bool ListSettings_200_response::isMmLiteEnabled() const +{ + return m_Mm_lite_enabled; +} + +void ListSettings_200_response::setMmLiteEnabled(bool value) +{ + m_Mm_lite_enabled = value; + m_Mm_lite_enabledIsSet = true; +} + +bool ListSettings_200_response::mmLiteEnabledIsSet() const +{ + return m_Mm_lite_enabledIsSet; +} + +void ListSettings_200_response::unsetMm_lite_enabled() +{ + m_Mm_lite_enabledIsSet = false; +} +bool ListSettings_200_response::isTemplateAnalyticsEnabled() const +{ + return m_Template_analytics_enabled; +} + +void ListSettings_200_response::setTemplateAnalyticsEnabled(bool value) +{ + m_Template_analytics_enabled = value; + m_Template_analytics_enabledIsSet = true; +} + +bool ListSettings_200_response::templateAnalyticsEnabledIsSet() const +{ + return m_Template_analytics_enabledIsSet; +} + +void ListSettings_200_response::unsetTemplate_analytics_enabled() +{ + m_Template_analytics_enabledIsSet = false; +} +bool ListSettings_200_response::isCtaUrlLinkTrackingOptedOut() const +{ + return m_Cta_url_link_tracking_opted_out; +} + +void ListSettings_200_response::setCtaUrlLinkTrackingOptedOut(bool value) +{ + m_Cta_url_link_tracking_opted_out = value; + m_Cta_url_link_tracking_opted_outIsSet = true; +} + +bool ListSettings_200_response::ctaUrlLinkTrackingOptedOutIsSet() const +{ + return m_Cta_url_link_tracking_opted_outIsSet; +} + +void ListSettings_200_response::unsetCta_url_link_tracking_opted_out() +{ + m_Cta_url_link_tracking_opted_outIsSet = false; +} +bool ListSettings_200_response::isHaveDisabledWebhooks() const +{ + return m_HaveDisabledWebhooks; +} + +void ListSettings_200_response::setHaveDisabledWebhooks(bool value) +{ + m_HaveDisabledWebhooks = value; + m_HaveDisabledWebhooksIsSet = true; +} + +bool ListSettings_200_response::haveDisabledWebhooksIsSet() const +{ + return m_HaveDisabledWebhooksIsSet; +} + +void ListSettings_200_response::unsetHaveDisabledWebhooks() +{ + m_HaveDisabledWebhooksIsSet = false; +} +ListSettings_200_response::CircuitStateEnum ListSettings_200_response::getCircuitState() const +{ + return m_CircuitState; +} + + +void ListSettings_200_response::setCircuitState(const CircuitStateEnum value) +{ + m_CircuitState = value; + m_CircuitStateIsSet = true; +} + +bool ListSettings_200_response::circuitStateIsSet() const +{ + return m_CircuitStateIsSet; +} + +void ListSettings_200_response::unsetCircuitState() +{ + m_CircuitStateIsSet = false; +} +utility::string_t ListSettings_200_response::getReason() const +{ + return m_Reason; +} + + +void ListSettings_200_response::setReason(const utility::string_t& value) +{ + m_Reason = value; + m_ReasonIsSet = true; +} + +bool ListSettings_200_response::reasonIsSet() const +{ + return m_ReasonIsSet; +} + +void ListSettings_200_response::unsetReason() +{ + m_ReasonIsSet = false; +} +int32_t ListSettings_200_response::getFails() const +{ + return m_Fails; +} + +void ListSettings_200_response::setFails(int32_t value) +{ + m_Fails = value; + m_FailsIsSet = true; +} + +bool ListSettings_200_response::failsIsSet() const +{ + return m_FailsIsSet; +} + +void ListSettings_200_response::unsetFails() +{ + m_FailsIsSet = false; +} +int32_t ListSettings_200_response::getTrips() const +{ + return m_Trips; +} + +void ListSettings_200_response::setTrips(int32_t value) +{ + m_Trips = value; + m_TripsIsSet = true; +} + +bool ListSettings_200_response::tripsIsSet() const +{ + return m_TripsIsSet; +} + +void ListSettings_200_response::unsetTrips() +{ + m_TripsIsSet = false; +} +int32_t ListSettings_200_response::getDisabledAt() const +{ + return m_DisabledAt; +} + +void ListSettings_200_response::setDisabledAt(int32_t value) +{ + m_DisabledAt = value; + m_DisabledAtIsSet = true; +} + +bool ListSettings_200_response::disabledAtIsSet() const +{ + return m_DisabledAtIsSet; +} + +void ListSettings_200_response::unsetDisabledAt() +{ + m_DisabledAtIsSet = false; +} +int32_t ListSettings_200_response::getFirstFailAt() const +{ + return m_FirstFailAt; +} + +void ListSettings_200_response::setFirstFailAt(int32_t value) +{ + m_FirstFailAt = value; + m_FirstFailAtIsSet = true; +} + +bool ListSettings_200_response::firstFailAtIsSet() const +{ + return m_FirstFailAtIsSet; +} + +void ListSettings_200_response::unsetFirstFailAt() +{ + m_FirstFailAtIsSet = false; +} +int32_t ListSettings_200_response::getLastStatus() const +{ + return m_LastStatus; +} + +void ListSettings_200_response::setLastStatus(int32_t value) +{ + m_LastStatus = value; + m_LastStatusIsSet = true; +} + +bool ListSettings_200_response::lastStatusIsSet() const +{ + return m_LastStatusIsSet; +} + +void ListSettings_200_response::unsetLastStatus() +{ + m_LastStatusIsSet = false; +} +int32_t ListSettings_200_response::getNextProbeAt() const +{ + return m_NextProbeAt; +} + +void ListSettings_200_response::setNextProbeAt(int32_t value) +{ + m_NextProbeAt = value; + m_NextProbeAtIsSet = true; +} + +bool ListSettings_200_response::nextProbeAtIsSet() const +{ + return m_NextProbeAtIsSet; +} + +void ListSettings_200_response::unsetNextProbeAt() +{ + m_NextProbeAtIsSet = false; +} +std::vector>> ListSettings_200_response::getDisabledWebhooks() const +{ + return m_DisabledWebhooks; +} + + +void ListSettings_200_response::setDisabledWebhooks(const std::vector>>& value) +{ + m_DisabledWebhooks = value; + m_DisabledWebhooksIsSet = true; +} + +bool ListSettings_200_response::disabledWebhooksIsSet() const +{ + return m_DisabledWebhooksIsSet; +} + +void ListSettings_200_response::unsetDisabledWebhooks() +{ + m_DisabledWebhooksIsSet = false; +} +std::vector> ListSettings_200_response::getWebhookStatuses() const +{ + return m_WebhookStatuses; +} + + +void ListSettings_200_response::setWebhookStatuses(const std::vector>& value) +{ + m_WebhookStatuses = value; + m_WebhookStatusesIsSet = true; +} + +bool ListSettings_200_response::webhookStatusesIsSet() const +{ + return m_WebhookStatusesIsSet; +} + +void ListSettings_200_response::unsetWebhookStatuses() +{ + m_WebhookStatusesIsSet = false; +} + + +std::map ListSettings_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void ListSettings_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void ListSettings_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool ListSettings_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void ListSettings_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/ListSettings_200_response_webhookUrl.cpp b/src/model/ListSettings_200_response_webhookUrl.cpp new file mode 100644 index 0000000..fc51856 --- /dev/null +++ b/src/model/ListSettings_200_response_webhookUrl.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/ListSettings_200_response_webhookUrl.h" diff --git a/src/model/ListTemplates_200_response.cpp b/src/model/ListTemplates_200_response.cpp index 35edd84..6e37b87 100644 --- a/src/model/ListTemplates_200_response.cpp +++ b/src/model/ListTemplates_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/MessageSentResponse.cpp b/src/model/MessageSentResponse.cpp index fbd9c8b..591aad7 100644 --- a/src/model/MessageSentResponse.cpp +++ b/src/model/MessageSentResponse.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/PatchFlowsFlowIdAssets_200_response.cpp b/src/model/PatchFlowsFlowIdAssets_200_response.cpp index 9478ef2..388ab81 100644 --- a/src/model/PatchFlowsFlowIdAssets_200_response.cpp +++ b/src/model/PatchFlowsFlowIdAssets_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/PatchFlowsFlowIdAssets_request.cpp b/src/model/PatchFlowsFlowIdAssets_request.cpp new file mode 100644 index 0000000..e31036a --- /dev/null +++ b/src/model/PatchFlowsFlowIdAssets_request.cpp @@ -0,0 +1,122 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/PatchFlowsFlowIdAssets_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +PatchFlowsFlowIdAssets_request::PatchFlowsFlowIdAssets_request() +{ + m_FlowJsonIsSet = false; +} + +PatchFlowsFlowIdAssets_request::~PatchFlowsFlowIdAssets_request() +{ +} + +void PatchFlowsFlowIdAssets_request::validate() +{ + // TODO: implement validation +} + +web::json::value PatchFlowsFlowIdAssets_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_FlowJsonIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("flowJson"))] = ModelBase::toJson(m_FlowJson); + } + + return val; +} + +bool PatchFlowsFlowIdAssets_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("flowJson")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("flowJson"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setFlowJson; + ok &= ModelBase::fromJson(fieldValue, refVal_setFlowJson); + setFlowJson(refVal_setFlowJson); + + } + } + return ok; +} + +void PatchFlowsFlowIdAssets_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_FlowJsonIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("flowJson")), m_FlowJson)); + } +} + +bool PatchFlowsFlowIdAssets_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("flowJson")))) + { + std::map> refVal_setFlowJson; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("flowJson"))), refVal_setFlowJson ); + setFlowJson(refVal_setFlowJson); + } + return ok; +} + + +std::map> PatchFlowsFlowIdAssets_request::getFlowJson() const +{ + return m_FlowJson; +} + + +void PatchFlowsFlowIdAssets_request::setFlowJson(const std::map>& value) +{ + m_FlowJson = value; + m_FlowJsonIsSet = true; +} + +bool PatchFlowsFlowIdAssets_request::flowJsonIsSet() const +{ + return m_FlowJsonIsSet; +} + +void PatchFlowsFlowIdAssets_request::unsetFlowJson() +{ + m_FlowJsonIsSet = false; +} + +} +} +} + + diff --git a/src/model/PatchFlowsFlowIdMetadata_request.cpp b/src/model/PatchFlowsFlowIdMetadata_request.cpp new file mode 100644 index 0000000..5f16a9d --- /dev/null +++ b/src/model/PatchFlowsFlowIdMetadata_request.cpp @@ -0,0 +1,302 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/PatchFlowsFlowIdMetadata_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +PatchFlowsFlowIdMetadata_request::PatchFlowsFlowIdMetadata_request() +{ + m_Name = utility::conversions::to_string_t(""); + m_NameIsSet = false; + m_CategoriesIsSet = false; + m_EndpointUri = utility::conversions::to_string_t(""); + m_EndpointUriIsSet = false; +} + +PatchFlowsFlowIdMetadata_request::~PatchFlowsFlowIdMetadata_request() +{ +} + +void PatchFlowsFlowIdMetadata_request::validate() +{ + // TODO: implement validation +} + +web::json::value PatchFlowsFlowIdMetadata_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_NameIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("name"))] = ModelBase::toJson(m_Name); + } + if(m_CategoriesIsSet) + { + + std::vector refVal = fromCategoriesEnum(m_Categories); + val[utility::conversions::to_string_t(_XPLATSTR("categories"))] = ModelBase::toJson(refVal); + + } + if(m_EndpointUriIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("endpointUri"))] = ModelBase::toJson(m_EndpointUri); + } + + return val; +} + +bool PatchFlowsFlowIdMetadata_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("name"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromJson(fieldValue, refVal_setName); + setName(refVal_setName); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("categories")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("categories"))); + if(!fieldValue.is_null()) + { + std::vector refVal_setCategories; + ok &= ModelBase::fromJson(fieldValue, refVal_setCategories); + + setCategories(toCategoriesEnum(refVal_setCategories)); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("endpointUri")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("endpointUri"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setEndpointUri; + ok &= ModelBase::fromJson(fieldValue, refVal_setEndpointUri); + setEndpointUri(refVal_setEndpointUri); + + } + } + return ok; +} + +void PatchFlowsFlowIdMetadata_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_NameIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("name")), m_Name)); + } + if(m_CategoriesIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("categories")), fromCategoriesEnum(m_Categories))); + } + if(m_EndpointUriIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("endpointUri")), m_EndpointUri)); + } +} + +bool PatchFlowsFlowIdMetadata_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("name"))), refVal_setName ); + setName(refVal_setName); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("categories")))) + { + std::vector refVal_setCategories; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("categories"))), refVal_setCategories ); + setCategories(toCategoriesEnum(refVal_setCategories)); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("endpointUri")))) + { + utility::string_t refVal_setEndpointUri; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("endpointUri"))), refVal_setEndpointUri ); + setEndpointUri(refVal_setEndpointUri); + } + return ok; +} + +PatchFlowsFlowIdMetadata_request::CategoriesEnum PatchFlowsFlowIdMetadata_request::toCategoriesEnum(const utility::string_t& value) const +{ + + if (value == utility::conversions::to_string_t("SIGN_UP")) { + return CategoriesEnum::SIGN_UP; + } + + if (value == utility::conversions::to_string_t("SIGN_IN")) { + return CategoriesEnum::SIGN_IN; + } + + if (value == utility::conversions::to_string_t("APPOINTMENT_BOOKING")) { + return CategoriesEnum::APPOINTMENT_BOOKING; + } + + if (value == utility::conversions::to_string_t("LEAD_GENERATION")) { + return CategoriesEnum::LEAD_GENERATION; + } + + if (value == utility::conversions::to_string_t("CONTACT_US")) { + return CategoriesEnum::CONTACT_US; + } + + if (value == utility::conversions::to_string_t("CUSTOMER_SUPPORT")) { + return CategoriesEnum::CUSTOMER_SUPPORT; + } + + if (value == utility::conversions::to_string_t("SURVEY")) { + return CategoriesEnum::SURVEY; + } + + if (value == utility::conversions::to_string_t("OTHER")) { + return CategoriesEnum::OTHER; + } + + throw std::invalid_argument("Invalid value for conversion to std::vector"); +} + +const utility::string_t PatchFlowsFlowIdMetadata_request::fromCategoriesEnum(const CategoriesEnum value) const +{ + switch(value) + { + + case CategoriesEnum::SIGN_UP: return utility::conversions::to_string_t("SIGN_UP"); + + case CategoriesEnum::SIGN_IN: return utility::conversions::to_string_t("SIGN_IN"); + + case CategoriesEnum::APPOINTMENT_BOOKING: return utility::conversions::to_string_t("APPOINTMENT_BOOKING"); + + case CategoriesEnum::LEAD_GENERATION: return utility::conversions::to_string_t("LEAD_GENERATION"); + + case CategoriesEnum::CONTACT_US: return utility::conversions::to_string_t("CONTACT_US"); + + case CategoriesEnum::CUSTOMER_SUPPORT: return utility::conversions::to_string_t("CUSTOMER_SUPPORT"); + + case CategoriesEnum::SURVEY: return utility::conversions::to_string_t("SURVEY"); + + case CategoriesEnum::OTHER: return utility::conversions::to_string_t("OTHER"); + + } +} + +std::vector PatchFlowsFlowIdMetadata_request::fromCategoriesEnum(const std::vector& value) const +{ + std::vector ret; + for (auto it = value.begin(); it != value.end(); it++) { + ret.push_back(fromCategoriesEnum(*it)); + } + return ret; +} + +std::vector PatchFlowsFlowIdMetadata_request::toCategoriesEnum(const std::vector& value) const +{ + std::vector ret; + for (auto it = value.begin(); it != value.end(); it++) { + ret.push_back(toCategoriesEnum(*it)); + } + return ret; +} + +utility::string_t PatchFlowsFlowIdMetadata_request::getName() const +{ + return m_Name; +} + + +void PatchFlowsFlowIdMetadata_request::setName(const utility::string_t& value) +{ + m_Name = value; + m_NameIsSet = true; +} + +bool PatchFlowsFlowIdMetadata_request::nameIsSet() const +{ + return m_NameIsSet; +} + +void PatchFlowsFlowIdMetadata_request::unsetName() +{ + m_NameIsSet = false; +} +std::vector PatchFlowsFlowIdMetadata_request::getCategories() const +{ + return m_Categories; +} + + +void PatchFlowsFlowIdMetadata_request::setCategories(const std::vector value) +{ + m_Categories = value; + m_CategoriesIsSet = true; +} + +bool PatchFlowsFlowIdMetadata_request::categoriesIsSet() const +{ + return m_CategoriesIsSet; +} + +void PatchFlowsFlowIdMetadata_request::unsetCategories() +{ + m_CategoriesIsSet = false; +} +utility::string_t PatchFlowsFlowIdMetadata_request::getEndpointUri() const +{ + return m_EndpointUri; +} + + +void PatchFlowsFlowIdMetadata_request::setEndpointUri(const utility::string_t& value) +{ + m_EndpointUri = value; + m_EndpointUriIsSet = true; +} + +bool PatchFlowsFlowIdMetadata_request::endpointUriIsSet() const +{ + return m_EndpointUriIsSet; +} + +void PatchFlowsFlowIdMetadata_request::unsetEndpointUri() +{ + m_EndpointUriIsSet = false; +} + +} +} +} + + diff --git a/src/model/ProfileInfo.cpp b/src/model/ProfileInfo.cpp index 00c18f9..cd5cef6 100644 --- a/src/model/ProfileInfo.cpp +++ b/src/model/ProfileInfo.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/RemoveTemplate_request.cpp b/src/model/RemoveTemplate_request.cpp new file mode 100644 index 0000000..9f19aa0 --- /dev/null +++ b/src/model/RemoveTemplate_request.cpp @@ -0,0 +1,123 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/RemoveTemplate_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +RemoveTemplate_request::RemoveTemplate_request() +{ + m_Name = utility::conversions::to_string_t(""); + m_NameIsSet = false; +} + +RemoveTemplate_request::~RemoveTemplate_request() +{ +} + +void RemoveTemplate_request::validate() +{ + // TODO: implement validation +} + +web::json::value RemoveTemplate_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_NameIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("name"))] = ModelBase::toJson(m_Name); + } + + return val; +} + +bool RemoveTemplate_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("name"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromJson(fieldValue, refVal_setName); + setName(refVal_setName); + + } + } + return ok; +} + +void RemoveTemplate_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_NameIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("name")), m_Name)); + } +} + +bool RemoveTemplate_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + utility::string_t refVal_setName; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("name"))), refVal_setName ); + setName(refVal_setName); + } + return ok; +} + + +utility::string_t RemoveTemplate_request::getName() const +{ + return m_Name; +} + + +void RemoveTemplate_request::setName(const utility::string_t& value) +{ + m_Name = value; + m_NameIsSet = true; +} + +bool RemoveTemplate_request::nameIsSet() const +{ + return m_NameIsSet; +} + +void RemoveTemplate_request::unsetName() +{ + m_NameIsSet = false; +} + +} +} +} + + diff --git a/src/model/RetrieveMedia_200_response.cpp b/src/model/RetrieveMedia_200_response.cpp index c714181..2e0c05f 100644 --- a/src/model/RetrieveMedia_200_response.cpp +++ b/src/model/RetrieveMedia_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendAddressMessage_request.cpp b/src/model/SendAddressMessage_request.cpp index 4a7d10b..750b5bb 100644 --- a/src/model/SendAddressMessage_request.cpp +++ b/src/model/SendAddressMessage_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendButton_request.cpp b/src/model/SendButton_request.cpp index c74cb87..cb899ec 100644 --- a/src/model/SendButton_request.cpp +++ b/src/model/SendButton_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,10 +22,16 @@ SendButton_request::SendButton_request() { m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; m_Body = utility::conversions::to_string_t(""); m_BodyIsSet = false; m_Footer = utility::conversions::to_string_t(""); m_FooterIsSet = false; + m_HeaderIsSet = false; + m_ButtonsIsSet = false; m_SectionsIsSet = false; } @@ -46,6 +52,16 @@ web::json::value SendButton_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } if(m_BodyIsSet) { @@ -56,6 +72,16 @@ web::json::value SendButton_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("footer"))] = ModelBase::toJson(m_Footer); } + if(m_HeaderIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("header"))] = ModelBase::toJson(m_Header); + } + if(m_ButtonsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("buttons"))] = ModelBase::toJson(m_Buttons); + } if(m_SectionsIsSet) { @@ -79,6 +105,28 @@ bool SendButton_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); @@ -101,6 +149,28 @@ bool SendButton_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("header")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("header"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setHeader; + ok &= ModelBase::fromJson(fieldValue, refVal_setHeader); + setHeader(refVal_setHeader); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("buttons")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("buttons"))); + if(!fieldValue.is_null()) + { + std::vector> refVal_setButtons; + ok &= ModelBase::fromJson(fieldValue, refVal_setButtons); + setButtons(refVal_setButtons); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("sections")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("sections"))); @@ -126,6 +196,14 @@ void SendButton_request::toMultipart(std::shared_ptr multipar { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } if(m_BodyIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); @@ -134,6 +212,14 @@ void SendButton_request::toMultipart(std::shared_ptr multipar { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("footer")), m_Footer)); } + if(m_HeaderIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("header")), m_Header)); + } + if(m_ButtonsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("buttons")), m_Buttons)); + } if(m_SectionsIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("sections")), m_Sections)); @@ -155,6 +241,18 @@ bool SendButton_request::fromMultiPart(std::shared_ptr multip ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) { utility::string_t refVal_setBody; @@ -167,6 +265,18 @@ bool SendButton_request::fromMultiPart(std::shared_ptr multip ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("footer"))), refVal_setFooter ); setFooter(refVal_setFooter); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("header")))) + { + std::map> refVal_setHeader; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("header"))), refVal_setHeader ); + setHeader(refVal_setHeader); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("buttons")))) + { + std::vector> refVal_setButtons; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("buttons"))), refVal_setButtons ); + setButtons(refVal_setButtons); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("sections")))) { std::vector> refVal_setSections; @@ -198,6 +308,48 @@ void SendButton_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendButton_request::getChatId() const +{ + return m_ChatId; +} + + +void SendButton_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendButton_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendButton_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendButton_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendButton_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendButton_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendButton_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} utility::string_t SendButton_request::getBody() const { return m_Body; @@ -240,6 +392,48 @@ void SendButton_request::unsetFooter() { m_FooterIsSet = false; } +std::map> SendButton_request::getHeader() const +{ + return m_Header; +} + + +void SendButton_request::setHeader(const std::map>& value) +{ + m_Header = value; + m_HeaderIsSet = true; +} + +bool SendButton_request::headerIsSet() const +{ + return m_HeaderIsSet; +} + +void SendButton_request::unsetHeader() +{ + m_HeaderIsSet = false; +} +std::vector> SendButton_request::getButtons() const +{ + return m_Buttons; +} + + +void SendButton_request::setButtons(const std::vector>& value) +{ + m_Buttons = value; + m_ButtonsIsSet = true; +} + +bool SendButton_request::buttonsIsSet() const +{ + return m_ButtonsIsSet; +} + +void SendButton_request::unsetButtons() +{ + m_ButtonsIsSet = false; +} std::vector> SendButton_request::getSections() const { return m_Sections; diff --git a/src/model/SendButton_request_sections_inner.cpp b/src/model/SendButton_request_sections_inner.cpp index df7e931..8579d4e 100644 --- a/src/model/SendButton_request_sections_inner.cpp +++ b/src/model/SendButton_request_sections_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendButton_request_sections_inner_reply.cpp b/src/model/SendButton_request_sections_inner_reply.cpp index b891cf1..fc5cbbd 100644 --- a/src/model/SendButton_request_sections_inner_reply.cpp +++ b/src/model/SendButton_request_sections_inner_reply.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendCarousel_request_1.cpp b/src/model/SendCarousel_request_1.cpp index a7f1a2f..51b9373 100644 --- a/src/model/SendCarousel_request_1.cpp +++ b/src/model/SendCarousel_request_1.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,6 +22,7 @@ SendCarousel_request_1::SendCarousel_request_1() { m_Body = utility::conversions::to_string_t(""); m_BodyIsSet = false; + m_CardsIsSet = false; m_ParamsIsSet = false; m_QuotedMsgId = utility::conversions::to_string_t(""); m_QuotedMsgIdIsSet = false; @@ -48,6 +49,11 @@ web::json::value SendCarousel_request_1::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("body"))] = ModelBase::toJson(m_Body); } + if(m_CardsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("cards"))] = ModelBase::toJson(m_Cards); + } if(m_ParamsIsSet) { @@ -86,6 +92,17 @@ bool SendCarousel_request_1::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("cards")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("cards"))); + if(!fieldValue.is_null()) + { + std::vector>> refVal_setCards; + ok &= ModelBase::fromJson(fieldValue, refVal_setCards); + setCards(refVal_setCards); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("params")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("params"))); @@ -144,6 +161,10 @@ void SendCarousel_request_1::toMultipart(std::shared_ptr mult { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); } + if(m_CardsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("cards")), m_Cards)); + } if(m_ParamsIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("params")), m_Params)); @@ -177,6 +198,12 @@ bool SendCarousel_request_1::fromMultiPart(std::shared_ptr mu ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("body"))), refVal_setBody ); setBody(refVal_setBody); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("cards")))) + { + std::vector>> refVal_setCards; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("cards"))), refVal_setCards ); + setCards(refVal_setCards); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("params")))) { std::vector> refVal_setParams; @@ -226,6 +253,27 @@ void SendCarousel_request_1::unsetBody() { m_BodyIsSet = false; } +std::vector>> SendCarousel_request_1::getCards() const +{ + return m_Cards; +} + + +void SendCarousel_request_1::setCards(const std::vector>>& value) +{ + m_Cards = value; + m_CardsIsSet = true; +} + +bool SendCarousel_request_1::cardsIsSet() const +{ + return m_CardsIsSet; +} + +void SendCarousel_request_1::unsetCards() +{ + m_CardsIsSet = false; +} std::vector> SendCarousel_request_1::getParams() const { return m_Params; diff --git a/src/model/SendContact_request.cpp b/src/model/SendContact_request.cpp index 94d86fc..38c2015 100644 --- a/src/model/SendContact_request.cpp +++ b/src/model/SendContact_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,6 +22,11 @@ SendContact_request::SendContact_request() { m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; + m_ContactIsSet = false; m_ContactsIsSet = false; } @@ -42,6 +47,21 @@ web::json::value SendContact_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } + if(m_ContactIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("contact"))] = ModelBase::toJson(m_Contact); + } if(m_ContactsIsSet) { @@ -65,6 +85,39 @@ bool SendContact_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("contact")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("contact"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setContact; + ok &= ModelBase::fromJson(fieldValue, refVal_setContact); + setContact(refVal_setContact); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("contacts")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("contacts"))); @@ -90,6 +143,18 @@ void SendContact_request::toMultipart(std::shared_ptr multipa { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } + if(m_ContactIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("contact")), m_Contact)); + } if(m_ContactsIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("contacts")), m_Contacts)); @@ -111,6 +176,24 @@ bool SendContact_request::fromMultiPart(std::shared_ptr multi ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("contact")))) + { + std::shared_ptr refVal_setContact; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("contact"))), refVal_setContact ); + setContact(refVal_setContact); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("contacts")))) { std::vector> refVal_setContacts; @@ -142,6 +225,69 @@ void SendContact_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendContact_request::getChatId() const +{ + return m_ChatId; +} + + +void SendContact_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendContact_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendContact_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendContact_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendContact_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendContact_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendContact_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} +std::shared_ptr SendContact_request::getContact() const +{ + return m_Contact; +} + + +void SendContact_request::setContact(const std::shared_ptr& value) +{ + m_Contact = value; + m_ContactIsSet = true; +} + +bool SendContact_request::contactIsSet() const +{ + return m_ContactIsSet; +} + +void SendContact_request::unsetContact() +{ + m_ContactIsSet = false; +} std::vector> SendContact_request::getContacts() const { return m_Contacts; diff --git a/src/model/SendContact_request_contact.cpp b/src/model/SendContact_request_contact.cpp new file mode 100644 index 0000000..da04825 --- /dev/null +++ b/src/model/SendContact_request_contact.cpp @@ -0,0 +1,317 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/SendContact_request_contact.h" + +namespace onemsg { +namespace sdk { +namespace model { + +SendContact_request_contact::SendContact_request_contact() +{ + m_NameIsSet = false; + m_Phone = utility::conversions::to_string_t(""); + m_PhoneIsSet = false; + m_Email = utility::conversions::to_string_t(""); + m_EmailIsSet = false; + m_OrgIsSet = false; + m_Url = utility::conversions::to_string_t(""); + m_UrlIsSet = false; +} + +SendContact_request_contact::~SendContact_request_contact() +{ +} + +void SendContact_request_contact::validate() +{ + // TODO: implement validation +} + +web::json::value SendContact_request_contact::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_NameIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("name"))] = ModelBase::toJson(m_Name); + } + if(m_PhoneIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); + } + if(m_EmailIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("email"))] = ModelBase::toJson(m_Email); + } + if(m_OrgIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("org"))] = ModelBase::toJson(m_Org); + } + if(m_UrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("url"))] = ModelBase::toJson(m_Url); + } + + return val; +} + +bool SendContact_request_contact::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("name"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setName; + ok &= ModelBase::fromJson(fieldValue, refVal_setName); + setName(refVal_setName); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("phone")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("phone"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setPhone; + ok &= ModelBase::fromJson(fieldValue, refVal_setPhone); + setPhone(refVal_setPhone); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("email")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("email"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setEmail; + ok &= ModelBase::fromJson(fieldValue, refVal_setEmail); + setEmail(refVal_setEmail); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("org")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("org"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setOrg; + ok &= ModelBase::fromJson(fieldValue, refVal_setOrg); + setOrg(refVal_setOrg); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("url"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setUrl); + setUrl(refVal_setUrl); + + } + } + return ok; +} + +void SendContact_request_contact::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_NameIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("name")), m_Name)); + } + if(m_PhoneIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); + } + if(m_EmailIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("email")), m_Email)); + } + if(m_OrgIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("org")), m_Org)); + } + if(m_UrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("url")), m_Url)); + } +} + +bool SendContact_request_contact::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("name")))) + { + std::shared_ptr refVal_setName; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("name"))), refVal_setName ); + setName(refVal_setName); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("phone")))) + { + utility::string_t refVal_setPhone; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); + setPhone(refVal_setPhone); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("email")))) + { + utility::string_t refVal_setEmail; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("email"))), refVal_setEmail ); + setEmail(refVal_setEmail); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("org")))) + { + std::map> refVal_setOrg; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("org"))), refVal_setOrg ); + setOrg(refVal_setOrg); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("url"))), refVal_setUrl ); + setUrl(refVal_setUrl); + } + return ok; +} + + +std::shared_ptr SendContact_request_contact::getName() const +{ + return m_Name; +} + + +void SendContact_request_contact::setName(const std::shared_ptr& value) +{ + m_Name = value; + m_NameIsSet = true; +} + +bool SendContact_request_contact::nameIsSet() const +{ + return m_NameIsSet; +} + +void SendContact_request_contact::unsetName() +{ + m_NameIsSet = false; +} +utility::string_t SendContact_request_contact::getPhone() const +{ + return m_Phone; +} + + +void SendContact_request_contact::setPhone(const utility::string_t& value) +{ + m_Phone = value; + m_PhoneIsSet = true; +} + +bool SendContact_request_contact::phoneIsSet() const +{ + return m_PhoneIsSet; +} + +void SendContact_request_contact::unsetPhone() +{ + m_PhoneIsSet = false; +} +utility::string_t SendContact_request_contact::getEmail() const +{ + return m_Email; +} + + +void SendContact_request_contact::setEmail(const utility::string_t& value) +{ + m_Email = value; + m_EmailIsSet = true; +} + +bool SendContact_request_contact::emailIsSet() const +{ + return m_EmailIsSet; +} + +void SendContact_request_contact::unsetEmail() +{ + m_EmailIsSet = false; +} +std::map> SendContact_request_contact::getOrg() const +{ + return m_Org; +} + + +void SendContact_request_contact::setOrg(const std::map>& value) +{ + m_Org = value; + m_OrgIsSet = true; +} + +bool SendContact_request_contact::orgIsSet() const +{ + return m_OrgIsSet; +} + +void SendContact_request_contact::unsetOrg() +{ + m_OrgIsSet = false; +} +utility::string_t SendContact_request_contact::getUrl() const +{ + return m_Url; +} + + +void SendContact_request_contact::setUrl(const utility::string_t& value) +{ + m_Url = value; + m_UrlIsSet = true; +} + +bool SendContact_request_contact::urlIsSet() const +{ + return m_UrlIsSet; +} + +void SendContact_request_contact::unsetUrl() +{ + m_UrlIsSet = false; +} + +} +} +} + + diff --git a/src/model/SendContact_request_contact_name.cpp b/src/model/SendContact_request_contact_name.cpp new file mode 100644 index 0000000..4bfe350 --- /dev/null +++ b/src/model/SendContact_request_contact_name.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/SendContact_request_contact_name.h" diff --git a/src/model/SendContact_request_contacts_inner.cpp b/src/model/SendContact_request_contacts_inner.cpp index 5eabc02..0c79332 100644 --- a/src/model/SendContact_request_contacts_inner.cpp +++ b/src/model/SendContact_request_contacts_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -111,7 +111,7 @@ bool SendContact_request_contacts_inner::fromJson(const web::json::value& val) const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("addresses"))); if(!fieldValue.is_null()) { - std::vector> refVal_setAddresses; + std::vector>> refVal_setAddresses; ok &= ModelBase::fromJson(fieldValue, refVal_setAddresses); setAddresses(refVal_setAddresses); @@ -122,7 +122,7 @@ bool SendContact_request_contacts_inner::fromJson(const web::json::value& val) const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("emails"))); if(!fieldValue.is_null()) { - std::vector> refVal_setEmails; + std::vector>> refVal_setEmails; ok &= ModelBase::fromJson(fieldValue, refVal_setEmails); setEmails(refVal_setEmails); @@ -155,7 +155,7 @@ bool SendContact_request_contacts_inner::fromJson(const web::json::value& val) const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("urls"))); if(!fieldValue.is_null()) { - std::vector> refVal_setUrls; + std::vector>> refVal_setUrls; ok &= ModelBase::fromJson(fieldValue, refVal_setUrls); setUrls(refVal_setUrls); @@ -224,13 +224,13 @@ bool SendContact_request_contacts_inner::fromMultiPart(std::shared_ptrhasContent(utility::conversions::to_string_t(_XPLATSTR("addresses")))) { - std::vector> refVal_setAddresses; + std::vector>> refVal_setAddresses; ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("addresses"))), refVal_setAddresses ); setAddresses(refVal_setAddresses); } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("emails")))) { - std::vector> refVal_setEmails; + std::vector>> refVal_setEmails; ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("emails"))), refVal_setEmails ); setEmails(refVal_setEmails); } @@ -248,7 +248,7 @@ bool SendContact_request_contacts_inner::fromMultiPart(std::shared_ptrhasContent(utility::conversions::to_string_t(_XPLATSTR("urls")))) { - std::vector> refVal_setUrls; + std::vector>> refVal_setUrls; ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("urls"))), refVal_setUrls ); setUrls(refVal_setUrls); } @@ -298,13 +298,13 @@ void SendContact_request_contacts_inner::unsetBirthday() { m_BirthdayIsSet = false; } -std::vector> SendContact_request_contacts_inner::getAddresses() const +std::vector>> SendContact_request_contacts_inner::getAddresses() const { return m_Addresses; } -void SendContact_request_contacts_inner::setAddresses(const std::vector>& value) +void SendContact_request_contacts_inner::setAddresses(const std::vector>>& value) { m_Addresses = value; m_AddressesIsSet = true; @@ -319,13 +319,13 @@ void SendContact_request_contacts_inner::unsetAddresses() { m_AddressesIsSet = false; } -std::vector> SendContact_request_contacts_inner::getEmails() const +std::vector>> SendContact_request_contacts_inner::getEmails() const { return m_Emails; } -void SendContact_request_contacts_inner::setEmails(const std::vector>& value) +void SendContact_request_contacts_inner::setEmails(const std::vector>>& value) { m_Emails = value; m_EmailsIsSet = true; @@ -382,13 +382,13 @@ void SendContact_request_contacts_inner::unsetPhones() { m_PhonesIsSet = false; } -std::vector> SendContact_request_contacts_inner::getUrls() const +std::vector>> SendContact_request_contacts_inner::getUrls() const { return m_Urls; } -void SendContact_request_contacts_inner::setUrls(const std::vector>& value) +void SendContact_request_contacts_inner::setUrls(const std::vector>>& value) { m_Urls = value; m_UrlsIsSet = true; diff --git a/src/model/SendContact_request_contacts_inner_name.cpp b/src/model/SendContact_request_contacts_inner_name.cpp index 27a24b6..fd9cb02 100644 --- a/src/model/SendContact_request_contacts_inner_name.cpp +++ b/src/model/SendContact_request_contacts_inner_name.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendContact_request_contacts_inner_org.cpp b/src/model/SendContact_request_contacts_inner_org.cpp index 7a2772d..2e9e093 100644 --- a/src/model/SendContact_request_contacts_inner_org.cpp +++ b/src/model/SendContact_request_contacts_inner_org.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendContact_request_contacts_inner_phones_inner.cpp b/src/model/SendContact_request_contacts_inner_phones_inner.cpp index 79ebf78..bf53329 100644 --- a/src/model/SendContact_request_contacts_inner_phones_inner.cpp +++ b/src/model/SendContact_request_contacts_inner_phones_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendCtaUrl_request.cpp b/src/model/SendCtaUrl_request.cpp index 4b1ae49..d7a8866 100644 --- a/src/model/SendCtaUrl_request.cpp +++ b/src/model/SendCtaUrl_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendFileRequest.cpp b/src/model/SendFileRequest.cpp index 788ff49..f3c57d9 100644 --- a/src/model/SendFileRequest.cpp +++ b/src/model/SendFileRequest.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendFlow_request_1.cpp b/src/model/SendFlow_request_1.cpp index fc96904..e5ffd7e 100644 --- a/src/model/SendFlow_request_1.cpp +++ b/src/model/SendFlow_request_1.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendFlow_request_1_header.cpp b/src/model/SendFlow_request_1_header.cpp index b430c30..b761efe 100644 --- a/src/model/SendFlow_request_1_header.cpp +++ b/src/model/SendFlow_request_1_header.cpp @@ -1,71 +1,2 @@ -/** - * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ - * - * The version of the OpenAPI document: 1.0.0 - * Contact: support@1msg.io - * - * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - - +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. #include "one-msg-sdk/model/SendFlow_request_1_header.h" - -namespace onemsg { -namespace sdk { -namespace model { - -void SendFlow_request_1_header::validate() -{ - // TODO: implement validation -} - -const SendFlow_request_1_header::VariantType& SendFlow_request_1_header::getVariant() const -{ - return m_variantValue; -} - -void SendFlow_request_1_header::setVariant(SendFlow_request_1_header::VariantType value) -{ - m_variantValue = value; -} - -web::json::value SendFlow_request_1_header::toJson() const -{ - web::json::value val = web::json::value::object(); - - std::visit([&](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - val = web::json::value::null(); - } else { - val = arg.toJson(); - } - }, m_variantValue); - - return val; -} - -void SendFlow_request_1_header::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const -{ - std::visit([&](auto&& arg) { - using T = std::decay_t; - if constexpr (!std::is_same_v) { - arg.toMultipart(multipart, prefix); - } - }, m_variantValue); -} - -template bool SendFlow_request_1_header::fromJson(const web::json::value& json); -template bool SendFlow_request_1_header::fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix); -template bool SendFlow_request_1_header::fromJson(const web::json::value& json); -template bool SendFlow_request_1_header::fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix); - -} -} -} - - diff --git a/src/model/SendFlow_request_header.cpp b/src/model/SendFlow_request_header.cpp index 337745a..0cbc220 100644 --- a/src/model/SendFlow_request_header.cpp +++ b/src/model/SendFlow_request_header.cpp @@ -1,71 +1,2 @@ -/** - * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ - * - * The version of the OpenAPI document: 1.0.0 - * Contact: support@1msg.io - * - * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - - +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. #include "one-msg-sdk/model/SendFlow_request_header.h" - -namespace onemsg { -namespace sdk { -namespace model { - -void SendFlow_request_header::validate() -{ - // TODO: implement validation -} - -const SendFlow_request_header::VariantType& SendFlow_request_header::getVariant() const -{ - return m_variantValue; -} - -void SendFlow_request_header::setVariant(SendFlow_request_header::VariantType value) -{ - m_variantValue = value; -} - -web::json::value SendFlow_request_header::toJson() const -{ - web::json::value val = web::json::value::object(); - - std::visit([&](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - val = web::json::value::null(); - } else { - val = arg.toJson(); - } - }, m_variantValue); - - return val; -} - -void SendFlow_request_header::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const -{ - std::visit([&](auto&& arg) { - using T = std::decay_t; - if constexpr (!std::is_same_v) { - arg.toMultipart(multipart, prefix); - } - }, m_variantValue); -} - -template bool SendFlow_request_header::fromJson(const web::json::value& json); -template bool SendFlow_request_header::fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix); -template bool SendFlow_request_header::fromJson(const web::json::value& json); -template bool SendFlow_request_header::fromMultiPart(std::shared_ptr multipart, const utility::string_t& namePrefix); - -} -} -} - - diff --git a/src/model/SendList_request.cpp b/src/model/SendList_request.cpp index 8669294..2a8b491 100644 --- a/src/model/SendList_request.cpp +++ b/src/model/SendList_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,6 +22,10 @@ SendList_request::SendList_request() { m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; m_Body = utility::conversions::to_string_t(""); m_BodyIsSet = false; m_ButtonText = utility::conversions::to_string_t(""); @@ -48,6 +52,16 @@ web::json::value SendList_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } if(m_BodyIsSet) { @@ -86,6 +100,28 @@ bool SendList_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); @@ -144,6 +180,14 @@ void SendList_request::toMultipart(std::shared_ptr multipart, { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } if(m_BodyIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); @@ -177,6 +221,18 @@ bool SendList_request::fromMultiPart(std::shared_ptr multipar ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) { utility::string_t refVal_setBody; @@ -226,6 +282,48 @@ void SendList_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendList_request::getChatId() const +{ + return m_ChatId; +} + + +void SendList_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendList_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendList_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendList_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendList_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendList_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendList_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} utility::string_t SendList_request::getBody() const { return m_Body; diff --git a/src/model/SendList_request_sections_inner.cpp b/src/model/SendList_request_sections_inner.cpp index cd46d31..ee5473e 100644 --- a/src/model/SendList_request_sections_inner.cpp +++ b/src/model/SendList_request_sections_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendList_request_sections_inner_rows_inner.cpp b/src/model/SendList_request_sections_inner_rows_inner.cpp index 8b99c9f..af424c4 100644 --- a/src/model/SendList_request_sections_inner_rows_inner.cpp +++ b/src/model/SendList_request_sections_inner_rows_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendLocationRequest_request.cpp b/src/model/SendLocationRequest_request.cpp index 12a1e0e..e7d9640 100644 --- a/src/model/SendLocationRequest_request.cpp +++ b/src/model/SendLocationRequest_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,6 +22,10 @@ SendLocationRequest_request::SendLocationRequest_request() { m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; m_Body = utility::conversions::to_string_t(""); m_BodyIsSet = false; } @@ -43,6 +47,16 @@ web::json::value SendLocationRequest_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } if(m_BodyIsSet) { @@ -66,6 +80,28 @@ bool SendLocationRequest_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); @@ -91,6 +127,14 @@ void SendLocationRequest_request::toMultipart(std::shared_ptr { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } if(m_BodyIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); @@ -112,6 +156,18 @@ bool SendLocationRequest_request::fromMultiPart(std::shared_ptrgetContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) { utility::string_t refVal_setBody; @@ -143,6 +199,48 @@ void SendLocationRequest_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendLocationRequest_request::getChatId() const +{ + return m_ChatId; +} + + +void SendLocationRequest_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendLocationRequest_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendLocationRequest_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendLocationRequest_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendLocationRequest_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendLocationRequest_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendLocationRequest_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} utility::string_t SendLocationRequest_request::getBody() const { return m_Body; diff --git a/src/model/SendLocation_request_1.cpp b/src/model/SendLocation_request_1.cpp index 2437780..d915af6 100644 --- a/src/model/SendLocation_request_1.cpp +++ b/src/model/SendLocation_request_1.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendMessageRequest.cpp b/src/model/SendMessageRequest.cpp index 65c342f..52b697a 100644 --- a/src/model/SendMessageRequest.cpp +++ b/src/model/SendMessageRequest.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendOrderDetails_request.cpp b/src/model/SendOrderDetails_request.cpp index a0c82b2..ce67448 100644 --- a/src/model/SendOrderDetails_request.cpp +++ b/src/model/SendOrderDetails_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendOrderDetails_request_language.cpp b/src/model/SendOrderDetails_request_language.cpp index 2e8699e..210583a 100644 --- a/src/model/SendOrderDetails_request_language.cpp +++ b/src/model/SendOrderDetails_request_language.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendOrderDetails_request_order.cpp b/src/model/SendOrderDetails_request_order.cpp index 4dcda29..e644ce6 100644 --- a/src/model/SendOrderDetails_request_order.cpp +++ b/src/model/SendOrderDetails_request_order.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendOrderDetails_request_order_items_inner.cpp b/src/model/SendOrderDetails_request_order_items_inner.cpp index 0be1283..50d400e 100644 --- a/src/model/SendOrderDetails_request_order_items_inner.cpp +++ b/src/model/SendOrderDetails_request_order_items_inner.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendOrderDetails_request_order_items_inner_amount.cpp b/src/model/SendOrderDetails_request_order_items_inner_amount.cpp index 73f1d33..cc8ee9c 100644 --- a/src/model/SendOrderDetails_request_order_items_inner_amount.cpp +++ b/src/model/SendOrderDetails_request_order_items_inner_amount.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendPaymentRequest_request.cpp b/src/model/SendPaymentRequest_request.cpp index 5b144d8..510fe14 100644 --- a/src/model/SendPaymentRequest_request.cpp +++ b/src/model/SendPaymentRequest_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendProduct_request.cpp b/src/model/SendProduct_request.cpp new file mode 100644 index 0000000..b6a15a1 --- /dev/null +++ b/src/model/SendProduct_request.cpp @@ -0,0 +1,471 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/SendProduct_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +SendProduct_request::SendProduct_request() +{ + m_Phone = utility::conversions::to_string_t(""); + m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; + m_Body = utility::conversions::to_string_t(""); + m_BodyIsSet = false; + m_Footer = utility::conversions::to_string_t(""); + m_FooterIsSet = false; + m_Header = utility::conversions::to_string_t(""); + m_HeaderIsSet = false; + m_ActionIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +SendProduct_request::~SendProduct_request() +{ +} + +void SendProduct_request::validate() +{ + // TODO: implement validation +} + +web::json::value SendProduct_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_PhoneIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); + } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } + if(m_BodyIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("body"))] = ModelBase::toJson(m_Body); + } + if(m_FooterIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("footer"))] = ModelBase::toJson(m_Footer); + } + if(m_HeaderIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("header"))] = ModelBase::toJson(m_Header); + } + if(m_ActionIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("action"))] = ModelBase::toJson(m_Action); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool SendProduct_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("phone")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("phone"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setPhone; + ok &= ModelBase::fromJson(fieldValue, refVal_setPhone); + setPhone(refVal_setPhone); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setBody; + ok &= ModelBase::fromJson(fieldValue, refVal_setBody); + setBody(refVal_setBody); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("footer")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("footer"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setFooter; + ok &= ModelBase::fromJson(fieldValue, refVal_setFooter); + setFooter(refVal_setFooter); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("header")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("header"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setHeader; + ok &= ModelBase::fromJson(fieldValue, refVal_setHeader); + setHeader(refVal_setHeader); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("action")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("action"))); + if(!fieldValue.is_null()) + { + std::map> refVal_setAction; + ok &= ModelBase::fromJson(fieldValue, refVal_setAction); + setAction(refVal_setAction); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("phone"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("chatId"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("body"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("footer"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("header"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("action"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void SendProduct_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_PhoneIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); + } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } + if(m_BodyIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); + } + if(m_FooterIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("footer")), m_Footer)); + } + if(m_HeaderIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("header")), m_Header)); + } + if(m_ActionIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("action")), m_Action)); + } +} + +bool SendProduct_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("phone")))) + { + utility::string_t refVal_setPhone; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); + setPhone(refVal_setPhone); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) + { + utility::string_t refVal_setBody; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("body"))), refVal_setBody ); + setBody(refVal_setBody); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("footer")))) + { + utility::string_t refVal_setFooter; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("footer"))), refVal_setFooter ); + setFooter(refVal_setFooter); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("header")))) + { + utility::string_t refVal_setHeader; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("header"))), refVal_setHeader ); + setHeader(refVal_setHeader); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("action")))) + { + std::map> refVal_setAction; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("action"))), refVal_setAction ); + setAction(refVal_setAction); + } + return ok; +} + + +utility::string_t SendProduct_request::getPhone() const +{ + return m_Phone; +} + + +void SendProduct_request::setPhone(const utility::string_t& value) +{ + m_Phone = value; + m_PhoneIsSet = true; +} + +bool SendProduct_request::phoneIsSet() const +{ + return m_PhoneIsSet; +} + +void SendProduct_request::unsetPhone() +{ + m_PhoneIsSet = false; +} +utility::string_t SendProduct_request::getChatId() const +{ + return m_ChatId; +} + + +void SendProduct_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendProduct_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendProduct_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendProduct_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendProduct_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendProduct_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendProduct_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} +utility::string_t SendProduct_request::getBody() const +{ + return m_Body; +} + + +void SendProduct_request::setBody(const utility::string_t& value) +{ + m_Body = value; + m_BodyIsSet = true; +} + +bool SendProduct_request::bodyIsSet() const +{ + return m_BodyIsSet; +} + +void SendProduct_request::unsetBody() +{ + m_BodyIsSet = false; +} +utility::string_t SendProduct_request::getFooter() const +{ + return m_Footer; +} + + +void SendProduct_request::setFooter(const utility::string_t& value) +{ + m_Footer = value; + m_FooterIsSet = true; +} + +bool SendProduct_request::footerIsSet() const +{ + return m_FooterIsSet; +} + +void SendProduct_request::unsetFooter() +{ + m_FooterIsSet = false; +} +utility::string_t SendProduct_request::getHeader() const +{ + return m_Header; +} + + +void SendProduct_request::setHeader(const utility::string_t& value) +{ + m_Header = value; + m_HeaderIsSet = true; +} + +bool SendProduct_request::headerIsSet() const +{ + return m_HeaderIsSet; +} + +void SendProduct_request::unsetHeader() +{ + m_HeaderIsSet = false; +} +std::map> SendProduct_request::getAction() const +{ + return m_Action; +} + + +void SendProduct_request::setAction(const std::map>& value) +{ + m_Action = value; + m_ActionIsSet = true; +} + +bool SendProduct_request::actionIsSet() const +{ + return m_ActionIsSet; +} + +void SendProduct_request::unsetAction() +{ + m_ActionIsSet = false; +} + + +std::map SendProduct_request::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void SendProduct_request::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void SendProduct_request::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool SendProduct_request::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void SendProduct_request::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/SendReaction_request.cpp b/src/model/SendReaction_request.cpp index 9907ab4..bdc4317 100644 --- a/src/model/SendReaction_request.cpp +++ b/src/model/SendReaction_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -22,6 +22,8 @@ SendReaction_request::SendReaction_request() { m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; m_Body = utility::conversions::to_string_t(""); m_BodyIsSet = false; m_QuotedMsgId = utility::conversions::to_string_t(""); @@ -45,6 +47,11 @@ web::json::value SendReaction_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } if(m_BodyIsSet) { @@ -73,6 +80,17 @@ bool SendReaction_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("body")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("body"))); @@ -109,6 +127,10 @@ void SendReaction_request::toMultipart(std::shared_ptr multip { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } if(m_BodyIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("body")), m_Body)); @@ -134,6 +156,12 @@ bool SendReaction_request::fromMultiPart(std::shared_ptr mult ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("body")))) { utility::string_t refVal_setBody; @@ -171,6 +199,27 @@ void SendReaction_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendReaction_request::getChatId() const +{ + return m_ChatId; +} + + +void SendReaction_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendReaction_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendReaction_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} utility::string_t SendReaction_request::getBody() const { return m_Body; diff --git a/src/model/SendSticker_request.cpp b/src/model/SendSticker_request.cpp index ce54149..3b657e1 100644 --- a/src/model/SendSticker_request.cpp +++ b/src/model/SendSticker_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SendTemplate_request.cpp b/src/model/SendTemplate_request.cpp index 9765740..fd452d0 100644 --- a/src/model/SendTemplate_request.cpp +++ b/src/model/SendTemplate_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io @@ -28,6 +28,10 @@ SendTemplate_request::SendTemplate_request() m_ParamsIsSet = false; m_Phone = utility::conversions::to_string_t(""); m_PhoneIsSet = false; + m_ChatId = utility::conversions::to_string_t(""); + m_ChatIdIsSet = false; + m_QuotedMsgId = utility::conversions::to_string_t(""); + m_QuotedMsgIdIsSet = false; m_UseMMlite = false; m_UseMMliteIsSet = false; m_MessageActivitySharing = false; @@ -73,6 +77,16 @@ web::json::value SendTemplate_request::toJson() const val[utility::conversions::to_string_t(_XPLATSTR("phone"))] = ModelBase::toJson(m_Phone); } + if(m_ChatIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("chatId"))] = ModelBase::toJson(m_ChatId); + } + if(m_QuotedMsgIdIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))] = ModelBase::toJson(m_QuotedMsgId); + } if(m_UseMMliteIsSet) { @@ -133,7 +147,7 @@ bool SendTemplate_request::fromJson(const web::json::value& val) const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("params"))); if(!fieldValue.is_null()) { - std::vector> refVal_setParams; + std::vector>> refVal_setParams; ok &= ModelBase::fromJson(fieldValue, refVal_setParams); setParams(refVal_setParams); @@ -150,6 +164,28 @@ bool SendTemplate_request::fromJson(const web::json::value& val) } } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("chatId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromJson(fieldValue, refVal_setChatId); + setChatId(refVal_setChatId); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromJson(fieldValue, refVal_setQuotedMsgId); + setQuotedMsgId(refVal_setQuotedMsgId); + + } + } if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("useMMlite")))) { const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("useMMlite"))); @@ -213,6 +249,14 @@ void SendTemplate_request::toMultipart(std::shared_ptr multip { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("phone")), m_Phone)); } + if(m_ChatIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("chatId")), m_ChatId)); + } + if(m_QuotedMsgIdIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")), m_QuotedMsgId)); + } if(m_UseMMliteIsSet) { multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("useMMlite")), m_UseMMlite)); @@ -256,7 +300,7 @@ bool SendTemplate_request::fromMultiPart(std::shared_ptr mult } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("params")))) { - std::vector> refVal_setParams; + std::vector>> refVal_setParams; ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("params"))), refVal_setParams ); setParams(refVal_setParams); } @@ -266,6 +310,18 @@ bool SendTemplate_request::fromMultiPart(std::shared_ptr mult ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("phone"))), refVal_setPhone ); setPhone(refVal_setPhone); } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("chatId")))) + { + utility::string_t refVal_setChatId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("chatId"))), refVal_setChatId ); + setChatId(refVal_setChatId); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId")))) + { + utility::string_t refVal_setQuotedMsgId; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("quotedMsgId"))), refVal_setQuotedMsgId ); + setQuotedMsgId(refVal_setQuotedMsgId); + } if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("useMMlite")))) { bool refVal_setUseMMlite; @@ -351,13 +407,13 @@ void SendTemplate_request::unsetr_namespace() { m_r_namespaceIsSet = false; } -std::vector> SendTemplate_request::getParams() const +std::vector>> SendTemplate_request::getParams() const { return m_Params; } -void SendTemplate_request::setParams(const std::vector>& value) +void SendTemplate_request::setParams(const std::vector>>& value) { m_Params = value; m_ParamsIsSet = true; @@ -393,6 +449,48 @@ void SendTemplate_request::unsetPhone() { m_PhoneIsSet = false; } +utility::string_t SendTemplate_request::getChatId() const +{ + return m_ChatId; +} + + +void SendTemplate_request::setChatId(const utility::string_t& value) +{ + m_ChatId = value; + m_ChatIdIsSet = true; +} + +bool SendTemplate_request::chatIdIsSet() const +{ + return m_ChatIdIsSet; +} + +void SendTemplate_request::unsetChatId() +{ + m_ChatIdIsSet = false; +} +utility::string_t SendTemplate_request::getQuotedMsgId() const +{ + return m_QuotedMsgId; +} + + +void SendTemplate_request::setQuotedMsgId(const utility::string_t& value) +{ + m_QuotedMsgId = value; + m_QuotedMsgIdIsSet = true; +} + +bool SendTemplate_request::quotedMsgIdIsSet() const +{ + return m_QuotedMsgIdIsSet; +} + +void SendTemplate_request::unsetQuotedMsgId() +{ + m_QuotedMsgIdIsSet = false; +} bool SendTemplate_request::isUseMMlite() const { return m_UseMMlite; diff --git a/src/model/SendTemplate_request_language.cpp b/src/model/SendTemplate_request_language.cpp index 250d7c5..9affb9f 100644 --- a/src/model/SendTemplate_request_language.cpp +++ b/src/model/SendTemplate_request_language.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SetWebhook_200_response.cpp b/src/model/SetWebhook_200_response.cpp new file mode 100644 index 0000000..2ccccdc --- /dev/null +++ b/src/model/SetWebhook_200_response.cpp @@ -0,0 +1,220 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/SetWebhook_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +SetWebhook_200_response::SetWebhook_200_response() +{ + m_set = false; + m_setIsSet = false; + m_WebhookUrlIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +SetWebhook_200_response::~SetWebhook_200_response() +{ +} + +void SetWebhook_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value SetWebhook_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_setIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("set"))] = ModelBase::toJson(m_set); + } + if(m_WebhookUrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool SetWebhook_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("set")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("set"))); + if(!fieldValue.is_null()) + { + bool refVal_setSet; + ok &= ModelBase::fromJson(fieldValue, refVal_setSet); + setSet(refVal_setSet); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookUrl); + setWebhookUrl(refVal_setWebhookUrl); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("set"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void SetWebhook_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_setIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("set")), m_set)); + } + if(m_WebhookUrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl)); + } +} + +bool SetWebhook_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("set")))) + { + bool refVal_setSet; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("set"))), refVal_setSet ); + setSet(refVal_setSet); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))), refVal_setWebhookUrl ); + setWebhookUrl(refVal_setWebhookUrl); + } + return ok; +} + + +bool SetWebhook_200_response::isSet() const +{ + return m_set; +} + +void SetWebhook_200_response::setSet(bool value) +{ + m_set = value; + m_setIsSet = true; +} + +bool SetWebhook_200_response::setIsSet() const +{ + return m_setIsSet; +} + +void SetWebhook_200_response::unsetset() +{ + m_setIsSet = false; +} +std::shared_ptr SetWebhook_200_response::getWebhookUrl() const +{ + return m_WebhookUrl; +} + + +void SetWebhook_200_response::setWebhookUrl(const std::shared_ptr& value) +{ + m_WebhookUrl = value; + m_WebhookUrlIsSet = true; +} + +bool SetWebhook_200_response::webhookUrlIsSet() const +{ + return m_WebhookUrlIsSet; +} + +void SetWebhook_200_response::unsetWebhookUrl() +{ + m_WebhookUrlIsSet = false; +} + + +std::map SetWebhook_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void SetWebhook_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void SetWebhook_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool SetWebhook_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void SetWebhook_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/SetWebhook_200_response_webhookUrl.cpp b/src/model/SetWebhook_200_response_webhookUrl.cpp new file mode 100644 index 0000000..4443238 --- /dev/null +++ b/src/model/SetWebhook_200_response_webhookUrl.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/SetWebhook_200_response_webhookUrl.h" diff --git a/src/model/SetWebhook_request.cpp b/src/model/SetWebhook_request.cpp new file mode 100644 index 0000000..710bcbe --- /dev/null +++ b/src/model/SetWebhook_request.cpp @@ -0,0 +1,171 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/SetWebhook_request.h" + +namespace onemsg { +namespace sdk { +namespace model { + +SetWebhook_request::SetWebhook_request() +{ + m_WebhookUrlIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +SetWebhook_request::~SetWebhook_request() +{ +} + +void SetWebhook_request::validate() +{ + // TODO: implement validation +} + +web::json::value SetWebhook_request::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_WebhookUrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))] = ModelBase::toJson(m_WebhookUrl); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool SetWebhook_request::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))); + if(!fieldValue.is_null()) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setWebhookUrl); + setWebhookUrl(refVal_setWebhookUrl); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void SetWebhook_request::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_WebhookUrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("webhookUrl")), m_WebhookUrl)); + } +} + +bool SetWebhook_request::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl")))) + { + std::shared_ptr refVal_setWebhookUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("webhookUrl"))), refVal_setWebhookUrl ); + setWebhookUrl(refVal_setWebhookUrl); + } + return ok; +} + + +std::shared_ptr SetWebhook_request::getWebhookUrl() const +{ + return m_WebhookUrl; +} + + +void SetWebhook_request::setWebhookUrl(const std::shared_ptr& value) +{ + m_WebhookUrl = value; + m_WebhookUrlIsSet = true; +} + +bool SetWebhook_request::webhookUrlIsSet() const +{ + return m_WebhookUrlIsSet; +} + +void SetWebhook_request::unsetWebhookUrl() +{ + m_WebhookUrlIsSet = false; +} + + +std::map SetWebhook_request::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void SetWebhook_request::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void SetWebhook_request::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool SetWebhook_request::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void SetWebhook_request::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/SetWebhook_request_webhookUrl.cpp b/src/model/SetWebhook_request_webhookUrl.cpp new file mode 100644 index 0000000..71c5c21 --- /dev/null +++ b/src/model/SetWebhook_request_webhookUrl.cpp @@ -0,0 +1,2 @@ +// Generated by quality/postprocess.mjs; implementation is inline to preserve union templates. +#include "one-msg-sdk/model/SetWebhook_request_webhookUrl.h" diff --git a/src/model/SetWhatsappBusinessEncryption_request.cpp b/src/model/SetWhatsappBusinessEncryption_request.cpp index 5564a7c..fc121dc 100644 --- a/src/model/SetWhatsappBusinessEncryption_request.cpp +++ b/src/model/SetWhatsappBusinessEncryption_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/SuccessResponse.cpp b/src/model/SuccessResponse.cpp index 3b2ff35..fe9b5e6 100644 --- a/src/model/SuccessResponse.cpp +++ b/src/model/SuccessResponse.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/UpdateCallingSettings_200_response.cpp b/src/model/UpdateCallingSettings_200_response.cpp index f690e1c..a96538f 100644 --- a/src/model/UpdateCallingSettings_200_response.cpp +++ b/src/model/UpdateCallingSettings_200_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/UpdateCallingSettings_200_response_response.cpp b/src/model/UpdateCallingSettings_200_response_response.cpp index 57b2a15..9312e53 100644 --- a/src/model/UpdateCallingSettings_200_response_response.cpp +++ b/src/model/UpdateCallingSettings_200_response_response.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/UpdateMe_200_response.cpp b/src/model/UpdateMe_200_response.cpp new file mode 100644 index 0000000..2abec13 --- /dev/null +++ b/src/model/UpdateMe_200_response.cpp @@ -0,0 +1,172 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/UpdateMe_200_response.h" + +namespace onemsg { +namespace sdk { +namespace model { + +UpdateMe_200_response::UpdateMe_200_response() +{ + m_Result = utility::conversions::to_string_t(""); + m_ResultIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +UpdateMe_200_response::~UpdateMe_200_response() +{ +} + +void UpdateMe_200_response::validate() +{ + // TODO: implement validation +} + +web::json::value UpdateMe_200_response::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_ResultIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("result"))] = ModelBase::toJson(m_Result); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool UpdateMe_200_response::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("result")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("result"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setResult; + ok &= ModelBase::fromJson(fieldValue, refVal_setResult); + setResult(refVal_setResult); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("result"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void UpdateMe_200_response::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_ResultIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("result")), m_Result)); + } +} + +bool UpdateMe_200_response::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("result")))) + { + utility::string_t refVal_setResult; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("result"))), refVal_setResult ); + setResult(refVal_setResult); + } + return ok; +} + + +utility::string_t UpdateMe_200_response::getResult() const +{ + return m_Result; +} + + +void UpdateMe_200_response::setResult(const utility::string_t& value) +{ + m_Result = value; + m_ResultIsSet = true; +} + +bool UpdateMe_200_response::resultIsSet() const +{ + return m_ResultIsSet; +} + +void UpdateMe_200_response::unsetResult() +{ + m_ResultIsSet = false; +} + + +std::map UpdateMe_200_response::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void UpdateMe_200_response::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void UpdateMe_200_response::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool UpdateMe_200_response::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void UpdateMe_200_response::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/src/model/UpdateMe_request.cpp b/src/model/UpdateMe_request.cpp index 22af03c..a95f327 100644 --- a/src/model/UpdateMe_request.cpp +++ b/src/model/UpdateMe_request.cpp @@ -1,6 +1,6 @@ /** * 1MSG WhatsApp Business API (Public) - * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** All requests require `token` query parameter with JWT or API key. **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ * * The version of the OpenAPI document: 1.0.0 * Contact: support@1msg.io diff --git a/src/model/WebhookUrlStatus.cpp b/src/model/WebhookUrlStatus.cpp new file mode 100644 index 0000000..7439558 --- /dev/null +++ b/src/model/WebhookUrlStatus.cpp @@ -0,0 +1,613 @@ +/** + * 1MSG WhatsApp Business API (Public) + * Public client API for sending messages, managing groups, flows, and templates. This is the API exposed to end customers via platform.1msg.io **Authentication:** Pass the channel token in **one** place. The API checks JSON body (`token`), then query string (`?token=`), then `Authorization: Bearer` header (preferred in production). **Documentation:** https://help.1msg.io/platform-1msg/getting-start/quick-start **API Docs:** https://docs.1msg.io/ + * + * The version of the OpenAPI document: 1.0.0 + * Contact: support@1msg.io + * + * NOTE: This class is auto generated by OpenAPI-Generator 7.22.0. + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +#include "one-msg-sdk/model/WebhookUrlStatus.h" + +namespace onemsg { +namespace sdk { +namespace model { + +WebhookUrlStatus::WebhookUrlStatus() +{ + m_Url = utility::conversions::to_string_t(""); + m_UrlIsSet = false; + m_CircuitStateIsSet = false; + m_Reason = utility::conversions::to_string_t(""); + m_ReasonIsSet = false; + m_Fails = 0; + m_FailsIsSet = false; + m_Trips = 0; + m_TripsIsSet = false; + m_DisabledAt = 0; + m_DisabledAtIsSet = false; + m_FirstFailAt = 0; + m_FirstFailAtIsSet = false; + m_LastStatus = 0; + m_LastStatusIsSet = false; + m_NextProbeAt = 0; + m_NextProbeAtIsSet = false; + m_AdditionalPropertiesIsSet = false; +} + +WebhookUrlStatus::~WebhookUrlStatus() +{ +} + +void WebhookUrlStatus::validate() +{ + // TODO: implement validation +} + +web::json::value WebhookUrlStatus::toJson() const +{ + web::json::value val = web::json::value::object(); + if(m_UrlIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("url"))] = ModelBase::toJson(m_Url); + } + if(m_CircuitStateIsSet) + { + + utility::string_t refVal = fromCircuitStateEnum(m_CircuitState); + val[utility::conversions::to_string_t(_XPLATSTR("circuitState"))] = ModelBase::toJson(refVal); + + } + if(m_ReasonIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("reason"))] = ModelBase::toJson(m_Reason); + } + if(m_FailsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("fails"))] = ModelBase::toJson(m_Fails); + } + if(m_TripsIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("trips"))] = ModelBase::toJson(m_Trips); + } + if(m_DisabledAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("disabledAt"))] = ModelBase::toJson(m_DisabledAt); + } + if(m_FirstFailAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))] = ModelBase::toJson(m_FirstFailAt); + } + if(m_LastStatusIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("lastStatus"))] = ModelBase::toJson(m_LastStatus); + } + if(m_NextProbeAtIsSet) + { + + val[utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))] = ModelBase::toJson(m_NextProbeAt); + } + // Serialize additional properties + if(m_AdditionalPropertiesIsSet) + { + for(const auto& item : m_AdditionalProperties) + { + val[item.first] = item.second; + } + } + + return val; +} + +bool WebhookUrlStatus::fromJson(const web::json::value& val) +{ + bool ok = true; + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("url"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromJson(fieldValue, refVal_setUrl); + setUrl(refVal_setUrl); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("circuitState"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromJson(fieldValue, refVal_setCircuitState); + + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("reason"))); + if(!fieldValue.is_null()) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromJson(fieldValue, refVal_setReason); + setReason(refVal_setReason); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("fails"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFails; + ok &= ModelBase::fromJson(fieldValue, refVal_setFails); + setFails(refVal_setFails); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("trips"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromJson(fieldValue, refVal_setTrips); + setTrips(refVal_setTrips); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setDisabledAt); + setDisabledAt(refVal_setDisabledAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setFirstFailAt); + setFirstFailAt(refVal_setFirstFailAt); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromJson(fieldValue, refVal_setLastStatus); + setLastStatus(refVal_setLastStatus); + + } + } + if(val.has_field(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + const web::json::value& fieldValue = val.at(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))); + if(!fieldValue.is_null()) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromJson(fieldValue, refVal_setNextProbeAt); + setNextProbeAt(refVal_setNextProbeAt); + + } + } + // Capture additional properties (keys not defined in the schema) + if(val.is_object()) + { + for(const auto& item : val.as_object()) + { + // Skip known properties + if(item.first == utility::conversions::to_string_t(_XPLATSTR("url"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("circuitState"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("reason"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("fails"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("trips"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("disabledAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("lastStatus"))) continue; + if(item.first == utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))) continue; + // This is an additional property + m_AdditionalProperties[item.first] = item.second; + m_AdditionalPropertiesIsSet = true; + } + } + return ok; +} + +void WebhookUrlStatus::toMultipart(std::shared_ptr multipart, const utility::string_t& prefix) const +{ + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + if(m_UrlIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("url")), m_Url)); + } + if(m_CircuitStateIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("circuitState")), fromCircuitStateEnum(m_CircuitState))); + } + if(m_ReasonIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("reason")), m_Reason)); + } + if(m_FailsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("fails")), m_Fails)); + } + if(m_TripsIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("trips")), m_Trips)); + } + if(m_DisabledAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("disabledAt")), m_DisabledAt)); + } + if(m_FirstFailAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("firstFailAt")), m_FirstFailAt)); + } + if(m_LastStatusIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("lastStatus")), m_LastStatus)); + } + if(m_NextProbeAtIsSet) + { + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")), m_NextProbeAt)); + } +} + +bool WebhookUrlStatus::fromMultiPart(std::shared_ptr multipart, const utility::string_t& prefix) +{ + bool ok = true; + utility::string_t namePrefix = prefix; + if(namePrefix.size() > 0 && namePrefix.substr(namePrefix.size() - 1) != utility::conversions::to_string_t(_XPLATSTR("."))) + { + namePrefix += utility::conversions::to_string_t(_XPLATSTR(".")); + } + + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("url")))) + { + utility::string_t refVal_setUrl; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("url"))), refVal_setUrl ); + setUrl(refVal_setUrl); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("circuitState")))) + { + utility::string_t refVal_setCircuitState; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("circuitState"))), refVal_setCircuitState ); + setCircuitState(toCircuitStateEnum(refVal_setCircuitState)); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("reason")))) + { + utility::string_t refVal_setReason; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("reason"))), refVal_setReason ); + setReason(refVal_setReason); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("fails")))) + { + int32_t refVal_setFails; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("fails"))), refVal_setFails ); + setFails(refVal_setFails); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("trips")))) + { + int32_t refVal_setTrips; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("trips"))), refVal_setTrips ); + setTrips(refVal_setTrips); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt")))) + { + int32_t refVal_setDisabledAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("disabledAt"))), refVal_setDisabledAt ); + setDisabledAt(refVal_setDisabledAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt")))) + { + int32_t refVal_setFirstFailAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("firstFailAt"))), refVal_setFirstFailAt ); + setFirstFailAt(refVal_setFirstFailAt); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus")))) + { + int32_t refVal_setLastStatus; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("lastStatus"))), refVal_setLastStatus ); + setLastStatus(refVal_setLastStatus); + } + if(multipart->hasContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt")))) + { + int32_t refVal_setNextProbeAt; + ok &= ModelBase::fromHttpContent(multipart->getContent(utility::conversions::to_string_t(_XPLATSTR("nextProbeAt"))), refVal_setNextProbeAt ); + setNextProbeAt(refVal_setNextProbeAt); + } + return ok; +} + +WebhookUrlStatus::CircuitStateEnum WebhookUrlStatus::toCircuitStateEnum(const utility::string_t& value) const +{ + + if (value == utility::conversions::to_string_t("ok")) { + return CircuitStateEnum::OK; + } + + if (value == utility::conversions::to_string_t("degraded")) { + return CircuitStateEnum::DEGRADED; + } + + if (value == utility::conversions::to_string_t("open")) { + return CircuitStateEnum::OPEN; + } + + if (value == utility::conversions::to_string_t("half_open")) { + return CircuitStateEnum::HALF_OPEN; + } + + if (value == utility::conversions::to_string_t("disabled")) { + return CircuitStateEnum::DISABLED; + } + + throw std::invalid_argument("Invalid value for conversion to CircuitStateEnum"); +} + + +const utility::string_t WebhookUrlStatus::fromCircuitStateEnum(const CircuitStateEnum value) const +{ + switch(value) + { + + case CircuitStateEnum::OK: return utility::conversions::to_string_t("ok"); + + case CircuitStateEnum::DEGRADED: return utility::conversions::to_string_t("degraded"); + + case CircuitStateEnum::OPEN: return utility::conversions::to_string_t("open"); + + case CircuitStateEnum::HALF_OPEN: return utility::conversions::to_string_t("half_open"); + + case CircuitStateEnum::DISABLED: return utility::conversions::to_string_t("disabled"); + + } +} + + +utility::string_t WebhookUrlStatus::getUrl() const +{ + return m_Url; +} + + +void WebhookUrlStatus::setUrl(const utility::string_t& value) +{ + m_Url = value; + m_UrlIsSet = true; +} + +bool WebhookUrlStatus::urlIsSet() const +{ + return m_UrlIsSet; +} + +void WebhookUrlStatus::unsetUrl() +{ + m_UrlIsSet = false; +} +WebhookUrlStatus::CircuitStateEnum WebhookUrlStatus::getCircuitState() const +{ + return m_CircuitState; +} + + +void WebhookUrlStatus::setCircuitState(const CircuitStateEnum value) +{ + m_CircuitState = value; + m_CircuitStateIsSet = true; +} + +bool WebhookUrlStatus::circuitStateIsSet() const +{ + return m_CircuitStateIsSet; +} + +void WebhookUrlStatus::unsetCircuitState() +{ + m_CircuitStateIsSet = false; +} +utility::string_t WebhookUrlStatus::getReason() const +{ + return m_Reason; +} + + +void WebhookUrlStatus::setReason(const utility::string_t& value) +{ + m_Reason = value; + m_ReasonIsSet = true; +} + +bool WebhookUrlStatus::reasonIsSet() const +{ + return m_ReasonIsSet; +} + +void WebhookUrlStatus::unsetReason() +{ + m_ReasonIsSet = false; +} +int32_t WebhookUrlStatus::getFails() const +{ + return m_Fails; +} + +void WebhookUrlStatus::setFails(int32_t value) +{ + m_Fails = value; + m_FailsIsSet = true; +} + +bool WebhookUrlStatus::failsIsSet() const +{ + return m_FailsIsSet; +} + +void WebhookUrlStatus::unsetFails() +{ + m_FailsIsSet = false; +} +int32_t WebhookUrlStatus::getTrips() const +{ + return m_Trips; +} + +void WebhookUrlStatus::setTrips(int32_t value) +{ + m_Trips = value; + m_TripsIsSet = true; +} + +bool WebhookUrlStatus::tripsIsSet() const +{ + return m_TripsIsSet; +} + +void WebhookUrlStatus::unsetTrips() +{ + m_TripsIsSet = false; +} +int32_t WebhookUrlStatus::getDisabledAt() const +{ + return m_DisabledAt; +} + +void WebhookUrlStatus::setDisabledAt(int32_t value) +{ + m_DisabledAt = value; + m_DisabledAtIsSet = true; +} + +bool WebhookUrlStatus::disabledAtIsSet() const +{ + return m_DisabledAtIsSet; +} + +void WebhookUrlStatus::unsetDisabledAt() +{ + m_DisabledAtIsSet = false; +} +int32_t WebhookUrlStatus::getFirstFailAt() const +{ + return m_FirstFailAt; +} + +void WebhookUrlStatus::setFirstFailAt(int32_t value) +{ + m_FirstFailAt = value; + m_FirstFailAtIsSet = true; +} + +bool WebhookUrlStatus::firstFailAtIsSet() const +{ + return m_FirstFailAtIsSet; +} + +void WebhookUrlStatus::unsetFirstFailAt() +{ + m_FirstFailAtIsSet = false; +} +int32_t WebhookUrlStatus::getLastStatus() const +{ + return m_LastStatus; +} + +void WebhookUrlStatus::setLastStatus(int32_t value) +{ + m_LastStatus = value; + m_LastStatusIsSet = true; +} + +bool WebhookUrlStatus::lastStatusIsSet() const +{ + return m_LastStatusIsSet; +} + +void WebhookUrlStatus::unsetLastStatus() +{ + m_LastStatusIsSet = false; +} +int32_t WebhookUrlStatus::getNextProbeAt() const +{ + return m_NextProbeAt; +} + +void WebhookUrlStatus::setNextProbeAt(int32_t value) +{ + m_NextProbeAt = value; + m_NextProbeAtIsSet = true; +} + +bool WebhookUrlStatus::nextProbeAtIsSet() const +{ + return m_NextProbeAtIsSet; +} + +void WebhookUrlStatus::unsetNextProbeAt() +{ + m_NextProbeAtIsSet = false; +} + + +std::map WebhookUrlStatus::getAdditionalProperties() const +{ + return m_AdditionalProperties; +} + +void WebhookUrlStatus::setAdditionalProperties(const std::map& value) +{ + m_AdditionalProperties = value; + m_AdditionalPropertiesIsSet = true; +} + +void WebhookUrlStatus::addAdditionalProperty(const utility::string_t& key, const web::json::value& value) +{ + m_AdditionalProperties[key] = value; + m_AdditionalPropertiesIsSet = true; +} + +bool WebhookUrlStatus::additionalPropertiesIsSet() const +{ + return m_AdditionalPropertiesIsSet; +} + +void WebhookUrlStatus::unsetAdditionalProperties() +{ + m_AdditionalProperties.clear(); + m_AdditionalPropertiesIsSet = false; +} +} +} +} + + diff --git a/tools/quality/README.md b/tools/quality/README.md new file mode 100644 index 0000000..ebb38d7 --- /dev/null +++ b/tools/quality/README.md @@ -0,0 +1,85 @@ +# 1MSG quality template 1.0.2 + +Vendored, private template for 1MSG-156. Install its exact tools with +`npm --prefix tools/quality ci` on Node 24.19.0. The lockfile and +`template-manifest.json` identify the reviewed version. This package is not +published to npm. Each consumer commits a full copy, its manifest, and its own +`quality.config.mjs` inventory. A version update requires policy review and +real negative fixtures; do not edit/reseal one consumer to hide a violation. + +## Profiles and commands + +A (Node runtime) and B (UI) require full static and typed ESLint, strict production, +test and tooling typechecks, architecture, debt gates, tests, and production build. +D applies these to authored TypeScript/tooling while each generated language uses +reproducible generation and native build/offline contract tests. C runs formatting +and static lint on every changed/new authored file and ratchets existing debt. +Compiler presets are provided for NodeNext, Next bundler and Svelte bundler; +consumers must include real sources/tests/tooling and the framework's generated types. + +Exported `staticConfig`, `typedConfig`, `maintainabilityConfig` compose with the +actual framework preset. Next uses its compatible core-web-vitals + TypeScript +presets and React Hooks; Svelte uses its parser/plugin and `svelte-check` on real +components. Browser globals and Node runtime checks have separate scopes. + +`node tools/quality/run.mjs guards` checks source inventory, suppressions, vendored +integrity and documentation for changed functions/private methods/substantive +callbacks plus full pilot roots. Comments explain purpose, effects and constraints; +AST coverage is mechanical, usefulness and accuracy require review. Formatting-only +changes do not create a method change. Meaningless boilerplate does not satisfy review. + +Mandatory graph/debt commands: `unused-production`, `unused-full`, `duplicates`. +`duplicates-full` saves the extended tests/fixtures report and fails analyzer errors; +it is a report, not the runtime clone gate. Configure `duplicatePaths`, +`duplicateFullPaths`, exact generated ignores, explicit formats, and an inventoried +numeric `duplicateMaxPercentage`. Detection uses minLines=5, minTokens=50, mild mode. +Clone groups cannot grow even if the overall duplicate percentage falls. + +Wrap actual JSON analyzer output with: + +- `report --kind eslint --name complexity -- node tools/quality/node_modules/eslint/bin/eslint.js . -c eslint.complexity.config.mjs -f json` +- `report --kind depcruiser --name architecture -- node tools/quality/node_modules/dependency-cruiser/bin/dependency-cruiser.mjs src --config dependency-cruiser.config.cjs --output-type json` + +Only maintainability metrics and existing runtime cycles are baselinable through +those report commands. Other static/typed/architecture diagnostics remain fatal. +Knip keeps separate production and full graphs; missing resolvers, empty graphs, +stale exclusions and malformed output are failures. Configure public exports and +dynamic entrypoints explicitly, never declare all source as entrypoints. + +## Historical debt + +Initial bootstrap is local only and requires owner, expiry, reason and issue: +`--bootstrap --owner TEAM --expires YYYY-MM-DD --reason TEXT --issue URL`. +It reruns the actual analyzer against the trusted Git base using the adopted +configuration. New files, disconnected imports and increased findings cannot be +blessed as historical debt. Replay removes only newly added entry/project patterns +that have no historical source; existing source always comes from Git archive. +Dependencies are shared read-only with the current installation for resolution. + +CI supplies the trusted PR base SHA through `QUALITY_BASE` and fetches full history. +After adoption, allowances cannot grow or renew their expiry; reductions and removed +findings must retire allowances. Reports include head/base SHAs and gate outcome. +Never describe a nonempty baseline as a clean codebase. + +## CI and local hooks + +Run `npm --prefix tools/quality test` as a mandatory independent check. Fixtures +execute actual Knip, jscpd and dependency-cruiser CLIs and verify ratchet growth, +coverage, documentation and malformed reports. Consumers add real typed/framework, +public API, native I/O, SQL, compatibility and generated-drift fixtures as applicable. +`Quality` / `quality-required` must aggregate all applicable checks and fail on any +missing, failed or cancelled required job. Configure this actual job context in +branch protection without removing existing requirements. CI never runs `--fix`. + +The pinned Husky/lint-staged dependencies support committed `.husky/pre-commit` and +an explicit repository `hooks:install` command. Keep hooks quick; CI is authoritative. +Do not change shared Git hook configuration of another worktree during verification. + +## Updating this template + +Change the template at its source, update its version, test actual consumers, +run `node seal.mjs`, copy the complete template, and commit lockfiles and inventory. +Integrity verification prevents hiding authored code under the vendor exemption. +No analyzer flag may depend on CI or a skip-type-aware environment variable. + +Version 1.0.2 resolves Svelte embedded clone paths to their physical source while retaining fragment identity. Initial Knip replay omits only the exact current-only sealed vendor ignore; authored stale ignores remain errors. diff --git a/tools/quality/eslint.mjs b/tools/quality/eslint.mjs new file mode 100644 index 0000000..142b9f1 --- /dev/null +++ b/tools/quality/eslint.mjs @@ -0,0 +1,137 @@ +import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import imports from 'eslint-plugin-import'; +import node from 'eslint-plugin-n'; +import unicorn from 'eslint-plugin-unicorn'; +import perfectionist from 'eslint-plugin-perfectionist'; +import sonarjs from 'eslint-plugin-sonarjs'; +import globals from 'globals'; +import { createRequire } from 'node:module'; + +const require = createRequire(import.meta.url); +export { + tseslint, + imports as importPlugin, + node as nodePlugin, + sonarjs, + unicorn, + perfectionist, + globals, +}; + +export const sourceFiles = ['**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}']; +export const testFiles = [ + '**/*.{test,spec,stories}.{js,jsx,ts,tsx}', + '**/{test,tests,__tests__,fixtures,mocks}/**', +]; + +/** Return the shared correctness/style layer; callers provide explicit browser/Node globals and generated paths. */ +export function staticConfig({ files = sourceFiles, globals = {} } = {}) { + return [ + { + files, + languageOptions: { globals }, + linterOptions: { reportUnusedDisableDirectives: 'error' }, + plugins: { import: imports, n: node, unicorn, perfectionist, sonarjs }, + settings: { + 'import/resolver': { + [require.resolve('eslint-import-resolver-typescript')]: { + alwaysTryTypes: true, + }, + node: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'] }, + }, + }, + rules: { + ...js.configs.recommended.rules, + eqeqeq: ['error', 'always'], + 'no-var': 'error', + 'prefer-const': 'error', + 'import/no-unresolved': 'error', + 'import/no-duplicates': 'error', + 'n/no-unsupported-features/node-builtins': [ + 'error', + { version: '>=24.0.0 <25.0.0' }, + ], + 'unicorn/prefer-node-protocol': 'error', + 'unicorn/prefer-type-error': 'error', + 'perfectionist/sort-imports': [ + 'error', + { type: 'natural', order: 'asc', sortSideEffects: false }, + ], + 'perfectionist/sort-exports': [ + 'error', + { type: 'natural', order: 'asc' }, + ], + 'sonarjs/no-identical-functions': 'error', + 'sonarjs/no-all-duplicated-branches': 'error', + }, + }, + ...tseslint.configs.recommended.map((config) => ({ + ...config, + files: ['**/*.{ts,tsx,cts,mts}'], + })), + ]; +} + +/** Apply mandatory type-aware Promise and unknown-boundary checks using actual repository tsconfigs. */ +export function typedConfig({ + files = ['**/*.{ts,tsx,cts,mts}'], + project, + tsconfigRootDir, +} = {}) { + return [ + { + files, + languageOptions: { + parser: tseslint.parser, + parserOptions: { project, tsconfigRootDir }, + }, + plugins: { '@typescript-eslint': tseslint.plugin }, + rules: { + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unsafe-assignment': 'error', + '@typescript-eslint/no-unsafe-argument': 'error', + '@typescript-eslint/no-unsafe-call': 'error', + '@typescript-eslint/no-unsafe-member-access': 'error', + '@typescript-eslint/no-unsafe-return': 'error', + }, + }, + ]; +} + +/** Keep complexity diagnostics separate so only measured maintainability debt can use a ratchet. */ +export function maintainabilityConfig({ files = sourceFiles } = {}) { + return [ + { + files, + ignores: testFiles, + plugins: { sonarjs }, + rules: { + 'max-lines': [ + 'error', + { max: 500, skipBlankLines: true, skipComments: true }, + ], + 'max-lines-per-function': [ + 'error', + { max: 80, skipBlankLines: true, skipComments: true }, + ], + complexity: ['error', { max: 20, variant: 'classic' }], + 'sonarjs/cognitive-complexity': ['error', 15], + 'max-depth': ['error', 4], + 'max-params': ['error', 5], + }, + }, + { + files: ['**/*.{jsx,tsx}'], + ignores: testFiles, + rules: { + 'max-lines-per-function': [ + 'error', + { max: 150, skipBlankLines: true, skipComments: true }, + ], + }, + }, + ]; +} diff --git a/tools/quality/lib/baseline.mjs b/tools/quality/lib/baseline.mjs new file mode 100644 index 0000000..b4e11a4 --- /dev/null +++ b/tools/quality/lib/baseline.mjs @@ -0,0 +1,82 @@ +import { createHash } from 'node:crypto'; + +/** Hash normalized evidence so line moves cannot grant new duplicate allowances. */ +export function digest(text) { + return createHash('sha256').update(text).digest('hex'); +} + +/** Keep a stable identifier for each independent finding, rather than a global failure count. */ +export function record(key, value = 1, details = {}) { + if (!key || !Number.isFinite(value) || value < 0) + throw new Error('Invalid analyzer finding'); + return { key, value, ...details }; +} + +/** Reject duplicate diagnostic identities because collapsing them could hide growing debt. */ +export function index(records) { + const result = new Map(); + for (const entry of records) { + if (result.has(entry.key)) + throw new Error(`Duplicate finding identity: ${entry.key}`); + result.set(entry.key, entry); + } + return result; +} + +/** Compare current findings with allowances and the trusted base's allowances, including stale debt. */ +export function assess( + findings, + baseline, + previous, + today = new Date().toISOString().slice(0, 10), +) { + const errors = []; + if (baseline.schemaVersion !== 1 || !Array.isArray(baseline.entries)) { + throw new Error('Unsupported or missing baseline schema'); + } + const current = index(findings); + const allowances = index(baseline.entries); + const older = previous ? index(previous.entries) : null; + for (const [key, allowance] of allowances) { + if ( + !allowance.owner || + !allowance.reason || + !allowance.issue || + !allowance.expires + ) { + errors.push(`Unowned/unexplained allowance: ${key}`); + } + if ( + !/^\d{4}-\d{2}-\d{2}$/.test(allowance.expires ?? '') || + allowance.expires < today + ) { + errors.push(`Expired or invalid allowance: ${key}`); + } + const finding = current.get(key); + if (!finding) errors.push(`Remove stale allowance: ${key}`); + else if (finding.value < allowance.value) + errors.push(`Reduce allowance to ${finding.value}: ${key}`); + if (older) { + const old = older.get(key); + if (!old || allowance.value > old.value) + errors.push(`Baseline expanded relative to trusted base: ${key}`); + if (old && allowance.expires > old.expires) + errors.push(`Allowance expiry extended: ${key}`); + } + } + for (const [key, finding] of current) { + if (!allowances.has(key) || finding.value > allowances.get(key).value) { + errors.push(`New or increased violation (${finding.value}): ${key}`); + } + } + return errors; +} + +/** Parse machine-readable output only; a missing report or unexpected schema is an analysis failure. */ +export function parseJson(stdout, analyzer) { + try { + return JSON.parse(stdout); + } catch { + throw new Error(`${analyzer} did not return a complete JSON report`); + } +} diff --git a/tools/quality/lib/git.mjs b/tools/quality/lib/git.mjs new file mode 100644 index 0000000..2aa6dcb --- /dev/null +++ b/tools/quality/lib/git.mjs @@ -0,0 +1,86 @@ +import { spawnSync } from 'node:child_process'; +import { readFileSync } from 'node:fs'; + +/** Run a bounded, non-shell child process; preserve failures instead of returning an empty analysis. */ +export function execute(command, args = [], options = {}) { + const result = spawnSync(command, args, { + encoding: 'utf8', + maxBuffer: 128 * 1024 * 1024, + timeout: 600_000, + ...options, + }); + if (result.error || result.signal || result.status === null) { + throw new Error( + `${command} did not complete: ${result.error?.message ?? result.signal}`, + ); + } + return result; +} + +/** Execute read-only Git operations and reject a missing ref or failed comparison. */ +export function git(args) { + const result = execute('git', args); + if (result.status !== 0) + throw new Error(`git ${args[0]} failed: ${result.stderr.trim()}`); + return result.stdout; +} + +/** Resolve one trusted comparison commit; CI explicitly supplies its PR base SHA. */ +export function baseRef( + defaultBranch = 'main', + explicit = process.env.QUALITY_BASE, +) { + if (explicit) + return git(['rev-parse', '--verify', `${explicit}^{commit}`]).trim(); + return git(['merge-base', 'HEAD', `origin/${defaultBranch}`]).trim(); +} + +/** Return tracked paths, including staged additions, with unambiguous NUL delimiters. */ +export function trackedFiles() { + return git(['ls-files', '-z']).split('\0').filter(Boolean); +} + +/** Include committed, staged, unstaged and untracked additions in local changed-file checks. */ +export function changedFiles(base) { + return [ + ...new Set( + [ + ...git([ + 'diff', + '--name-only', + '--diff-filter=ACMR', + '-z', + base, + '--', + ]).split('\0'), + ...git(['ls-files', '--others', '--exclude-standard', '-z']).split( + '\0', + ), + ].filter(Boolean), + ), + ].sort(); +} + +/** Read an optional file at the verified base; missing files mean additions, not failed Git. */ +export function baseFile(base, path) { + const paths = git([ + 'ls-tree', + '-r', + '--name-only', + '-z', + base, + '--', + path, + ]).split('\0'); + return paths.includes(path) ? git(['show', `${base}:${path}`]) : null; +} + +/** Read current bytes only when the path exists; deleted files have no current diagnostics. */ +export function currentFile(path) { + try { + return readFileSync(path, 'utf8'); + } catch (error) { + if (error.code === 'ENOENT') return null; + throw error; + } +} diff --git a/tools/quality/lib/guards.mjs b/tools/quality/lib/guards.mjs new file mode 100644 index 0000000..500c8fe --- /dev/null +++ b/tools/quality/lib/guards.mjs @@ -0,0 +1,356 @@ +import ts from 'typescript'; +import picomatch from 'picomatch'; +import { existsSync } from 'node:fs'; +import { baseFile, changedFiles, currentFile, trackedFiles } from './git.mjs'; +import { digest } from './baseline.mjs'; +import { verifyTemplate } from './template.mjs'; + +const sourcePattern = /\.(?:[cm]?[jt]sx?|svelte)$/; + +/** Match repo-relative paths consistently; generated and exception paths stay explicit. */ +export function matches(path, patterns = []) { + return patterns.some((pattern) => picomatch(pattern, { dot: true })(path)); +} + +/** Validate manifest entries before they can remove any source from a mandatory check. */ +export function validateConfig( + config, + today = new Date().toISOString().slice(0, 10), +) { + if ( + config.schemaVersion !== 1 || + !['A', 'B', 'C', 'D'].includes(config.profile) + ) { + throw new Error( + 'quality.config.mjs requires schemaVersion=1 and a concrete profile', + ); + } + if (!Array.isArray(config.sourceRoots) || config.sourceRoots.length === 0) { + throw new Error( + 'sourceRoots must inventory the authored source and tooling', + ); + } + for (const root of config.sourceRoots) { + if (!existsSync(root)) throw new Error(`Missing source root: ${root}`); + } + for (const entry of config.generated ?? []) { + if ( + !entry.producer || + !entry.pattern || + ['**', '**/*', '**/*.ts', '**/*.js'].includes(entry.pattern) + ) { + throw new Error( + 'Generated exclusions require a narrow path and actual producer', + ); + } + } + for (const entry of [ + ...(config.excluded ?? []), + ...(config.comments?.exclude ?? []), + ]) { + if ( + !entry.pattern || + !entry.owner || + !entry.reason || + !entry.expires || + entry.expires < today + ) { + throw new Error(`Unowned or expired source exception: ${entry.pattern}`); + } + } +} + +/** Parse script content with its actual syntax kind; Svelte markup is handled by framework checks. */ +export function parseUnits(path, text) { + if (path.endsWith('.svelte')) { + return [...text.matchAll(/]*)>([\s\S]*?)<\/script\s*>/g)].map( + (match, index) => ({ + suffix: `script${index}`, + ast: ts.createSourceFile( + path, + match[2], + ts.ScriptTarget.Latest, + true, + /lang\s*=\s*["']ts["']/.test(match[1]) + ? ts.ScriptKind.TS + : ts.ScriptKind.JS, + ), + }), + ); + } + const kind = path.endsWith('.tsx') + ? ts.ScriptKind.TSX + : path.endsWith('.jsx') + ? ts.ScriptKind.JSX + : /\.[cm]?ts$/.test(path) + ? ts.ScriptKind.TS + : ts.ScriptKind.JS; + return [ + { + suffix: '', + ast: ts.createSourceFile(path, text, ts.ScriptTarget.Latest, true, kind), + }, + ]; +} + +/** Compare semantic tokens so formatting/quote changes do not create a false method edit. */ +function functionFingerprint(fragment) { + const scanner = ts.createScanner( + ts.ScriptTarget.Latest, + true, + ts.LanguageVariant.JSX, + fragment, + ); + const tokens = []; + for ( + let token = scanner.scan(); + token !== ts.SyntaxKind.EndOfFileToken; + token = scanner.scan() + ) { + const value = [ + ts.SyntaxKind.StringLiteral, + ts.SyntaxKind.NoSubstitutionTemplateLiteral, + ].includes(token) + ? scanner.getTokenValue() + : scanner.getTokenText(); + tokens.push([token, value]); + } + const meaningful = tokens.filter(([kind], index) => { + if (kind !== ts.SyntaxKind.CommaToken) return true; + const next = tokens[index + 1]?.[0]; + if (next === ts.SyntaxKind.CloseBracketToken) { + // Array elisions change length and must never be treated as formatting. + const previous = tokens[index - 1]?.[0]; + return [ + ts.SyntaxKind.CommaToken, + ts.SyntaxKind.OpenBracketToken, + ].includes(previous); + } + return ![ + ts.SyntaxKind.CloseParenToken, + ts.SyntaxKind.CloseBraceToken, + ].includes(next); + }); + return digest(JSON.stringify(meaningful)); +} + +/** Identify callbacks by their lexical owner, not their position among unrelated functions. */ +function lexicalScope(node, ast) { + const owners = []; + for (let current = node.parent; current; current = current.parent) { + if (ts.isFunctionLike(current) || ts.isClassLike(current)) { + const name = current.name ?? current.parent?.name; + if (name) owners.push(name.getText(ast)); + } else if (ts.isCallExpression(current)) { + owners.push(current.expression.getText(ast)); + } + } + return owners.reverse().join('/'); +} + +/** Resolve a function's meaningful enclosing declaration for stable identity and adjacent documentation. */ +function declaration(node) { + let owner = node; + if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) { + if (ts.isVariableDeclaration(node.parent)) { + owner = node.parent.parent.parent; + } else if ( + ts.isPropertyAssignment(node.parent) || + ts.isPropertyDeclaration(node.parent) + ) { + owner = node.parent; + } + } + return owner; +} + +/** Read adjacent callback docs through casts/assignments, stopping at its own statement or enclosing function. */ +function callbackComments(node, ast) { + const comments = []; + let current = node; + while (current) { + if (current !== node && ts.isFunctionLike(current)) break; + const trivia = ast.text.slice( + current.getFullStart(), + current.getStart(ast), + ); + comments.push(...(trivia.match(/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g) ?? [])); + if (ts.isStatement(current)) break; + current = current.parent; + } + return comments; +} + +/** Extract all implemented functions, including private methods, factories and substantive callbacks. */ +export function functionsIn(path, text) { + const functions = []; + for (const { suffix, ast } of parseUnits(path, text)) { + if (ast.parseDiagnostics.length) + throw new Error( + `Cannot parse ${path}: ${ast.parseDiagnostics[0].messageText}`, + ); + const visit = (node) => { + if (ts.isFunctionLike(node) && node.body) { + const owner = declaration(node); + const name = + node.name?.getText(ast) ?? + node.parent.name?.getText(ast) ?? + ''; + const ranges = + ts.getLeadingCommentRanges(ast.text, owner.getFullStart()) ?? []; + const comments = ranges.map((range) => + ast.text.slice(range.pos, range.end), + ); + const parentComments = + node.parent && ts.isCallExpression(node.parent) + ? ( + ts.getLeadingCommentRanges( + ast.text, + node.parent.parent.getFullStart(), + ) ?? [] + ).map((range) => ast.text.slice(range.pos, range.end)) + : []; + functions.push({ + key: `${suffix}:${lexicalScope(node, ast)}:${name}`, + signature: functionFingerprint(node.getText(ast)), + name, + comments: [ + ...comments, + ...parentComments, + ...(name === '' ? callbackComments(node, ast) : []), + ], + line: ast.getLineAndCharacterOfPosition(node.getStart(ast)).line + 1, + callback: name === '', + // An expression-only projection has no independent scenario; its enclosing function is documented. + trivialCallback: + name === '' && + !ts.isBlock(node.body) && + node.body.getText(ast).length < 80 && + !/await|throw|fetch|\bnew\b/.test(node.body.getText(ast)), + }); + } + ts.forEachChild(node, visit); + }; + visit(ast); + } + return functions; +} + +/** Identify suppression directives in comments only, never in strings or generated documentation examples. */ +export function suppressionErrors(path, text, config) { + const errors = []; + for (const { ast } of parseUnits(path, text)) { + const scanner = ts.createScanner( + ts.ScriptTarget.Latest, + false, + ts.LanguageVariant.Standard, + ast.text, + ); + for ( + let token = scanner.scan(); + token !== ts.SyntaxKind.EndOfFileToken; + token = scanner.scan() + ) { + if ( + ![ + ts.SyntaxKind.SingleLineCommentTrivia, + ts.SyntaxKind.MultiLineCommentTrivia, + ].includes(token) + ) + continue; + const comment = scanner.getTokenText(); + if ( + /@ts-(?:ignore|nocheck)\b/.test(comment) || + /eslint-disable(?!-next-line|-line)\b/.test(comment) + ) { + errors.push(`${path}: broad lint/type suppression is forbidden`); + } + if ( + /eslint-disable(?:-next-line|-line)\b/.test(comment) && + !/eslint-disable(?:-next-line|-line)\s+[\w@/-]+(?:\s*,\s*[\w@/-]+)*\s+--\s+.{12,}/.test( + comment, + ) + ) { + errors.push( + `${path}: suppression must name rules and explain the scoped exception`, + ); + } + if ( + /@ts-expect-error\b/.test(comment) && + (!/@ts-expect-error\s*:?\s+.{12,}/.test(comment) || + !matches(path, config.negativeTypeTests ?? [])) + ) { + errors.push( + `${path}: @ts-expect-error requires an explained negative type-test scope`, + ); + } + } + } + return errors; +} + +/** Enforce complete authored-file coverage plus documentation on changed functions and pilot trees. */ +export function runGuards(config, base) { + validateConfig(config); + verifyTemplate(base); + const changed = new Set(changedFiles(base)); + const allFiles = [...new Set([...trackedFiles(), ...changed])]; + const generated = (config.generated ?? []).map((entry) => entry.pattern); + const excluded = (config.excluded ?? []).map((entry) => entry.pattern); + const errors = []; + let checked = 0; + for (const path of allFiles.filter((path) => sourcePattern.test(path))) { + if (path.startsWith('tools/quality/')) continue; // Versioned template has its own tests and documented API. + if (matches(path, [...generated, ...excluded])) continue; + if ( + !config.sourceRoots.some( + (root) => + root === '.' || + path === root || + path.startsWith(`${root.replace(/\/$/, '')}/`), + ) + ) { + errors.push(`${path}: authored file has no declared source root`); + continue; + } + const text = currentFile(path); + if (text === null) continue; + checked++; + const full = matches(path, config.comments?.full); + if (!changed.has(path) && !full) continue; + errors.push(...suppressionErrors(path, text, config)); + if ( + matches( + path, + (config.comments?.exclude ?? []).map((entry) => entry.pattern), + ) + ) + continue; + const before = baseFile(base, path); + const previous = new Map(); + for (const fn of before === null ? [] : functionsIn(path, before)) { + const identity = `${fn.key}:${fn.signature}`; + previous.set(identity, (previous.get(identity) ?? 0) + 1); + } + for (const fn of functionsIn(path, text)) { + const identity = `${fn.key}:${fn.signature}`; + const remaining = previous.get(identity) ?? 0; + if (remaining > 0) previous.set(identity, remaining - 1); + if ((!full && remaining > 0) || fn.trivialCallback) continue; + const docs = fn.comments + .filter((comment) => fn.callback || comment.startsWith('/**')) + .join('\n'); + const words = docs + .replace(/\{@[^}]+\}|\{[^}]+\}|\*|\//g, ' ') + .trim() + .split(/\s+/); + if (words.length < 3 || docs.length < 18) + errors.push( + `${path}:${fn.line}: document ${fn.name}'s purpose and contract`, + ); + } + } + if (checked === 0 && config.profile !== 'D') + errors.push('No authored JS/TS/Svelte files were checked'); + return { checked, errors }; +} diff --git a/tools/quality/lib/historical.mjs b/tools/quality/lib/historical.mjs new file mode 100644 index 0000000..7ed6be8 --- /dev/null +++ b/tools/quality/lib/historical.mjs @@ -0,0 +1,139 @@ +import { + cpSync, + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + symlinkSync, + writeFileSync, +} from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { tmpdir } from 'node:os'; +import { execute, git } from './git.mjs'; +import picomatch from 'picomatch'; + +/** Omit only new entry/project targets that cannot exist in the historical source being measured. */ +function historicalPatterns(value, prefix, currentPaths, basePaths) { + const patterns = typeof value === 'string' ? [value] : value; + if (!Array.isArray(patterns)) return value; + return patterns.filter((pattern) => { + if (typeof pattern !== 'string' || pattern.startsWith('!')) return true; + const match = picomatch( + join(prefix, pattern.replace(/!$/, '')).replaceAll('\\', '/'), + { dot: true }, + ); + return ( + basePaths.some((path) => match(path)) || + !currentPaths.some((path) => match(path)) + ); + }); +} + +/** Keep current Knip policy but remove newly introduced tooling-only roots from historical coverage. */ +function prepareHistoricalKnip(path, currentPaths, basePaths) { + if (!path.endsWith('.json') || !existsSync(path)) return; + const config = JSON.parse(readFileSync(path, 'utf8')); + // The sealed vendor snapshot is new during initial adoption. Its current-only + // import roots are removed below, so this exact exemption would otherwise be stale. + if ( + !basePaths.some((path) => path.startsWith('tools/quality/')) && + Array.isArray(config.ignore) + ) { + config.ignore = config.ignore.filter( + (pattern) => pattern !== 'tools/quality/**', + ); + } + const scopes = [['.', config], ...Object.entries(config.workspaces ?? {})]; + for (const [prefix, scope] of scopes) { + if (!scope || typeof scope !== 'object') continue; + for (const key of ['entry', 'project']) { + if (scope[key]) + scope[key] = historicalPatterns( + scope[key], + prefix, + currentPaths, + basePaths, + ); + } + } + writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`); +} + +/** Re-run the same analyzer against trusted source with the newly adopted analysis configuration. */ +export function historicalAnalysis(base, config, templateDirectory, analyze) { + const current = process.cwd(); + const snapshot = mkdtempSync(join(tmpdir(), '1msg-quality-base-')); + const archiveDirectory = mkdtempSync(join(tmpdir(), '1msg-quality-archive-')); + try { + const archivePath = join(archiveDirectory, 'source.tar'); + const archive = execute('git', [ + 'archive', + '--format=tar', + '--output', + archivePath, + base, + ]); + if (archive.status !== 0) + throw new Error(`Cannot read trusted source: ${archive.stderr}`); + const extract = execute('tar', ['-xf', archivePath, '-C', snapshot]); + if (extract.status !== 0) + throw new Error(`Cannot unpack trusted source: ${extract.stderr}`); + const paths = git(['ls-files', '-co', '--exclude-standard', '-z']) + .split('\0') + .filter(Boolean); + const basePaths = git(['ls-tree', '-r', '--name-only', '-z', base]) + .split('\0') + .filter(Boolean); + // Some legacy multi-package repos adopt their first root manifest with the quality tooling. + // Findings on this new manifest still cannot become debt: initialEvidence requires a base file. + if ( + !existsSync(join(snapshot, 'package.json')) && + existsSync('package.json') + ) { + cpSync('package.json', join(snapshot, 'package.json')); + } + const configuration = paths.filter((path) => + /(?:^|\/)(?:eslint(?:\.[\w-]+)?\.config\.[cm]?js|dependency-cruiser(?:\.[\w-]+)?\.config\.[cm]?js|tsconfig(?:\.[\w-]+)?\.json|quality\.config\.mjs)$/.test( + path, + ), + ); + configuration.push(config.knipConfig ?? 'knip.json'); + for (const path of new Set(configuration)) { + if (!existsSync(path)) continue; + mkdirSync(dirname(join(snapshot, path)), { recursive: true }); + cpSync(path, join(snapshot, path)); + } + prepareHistoricalKnip( + join(snapshot, config.knipConfig ?? 'knip.json'), + paths, + basePaths, + ); + // Dependencies are analyzer inputs; historical application source always comes from Git above. + const packages = new Set([ + '.', + ...paths.filter((path) => path.endsWith('/package.json')).map(dirname), + ]); + for (const path of packages) { + const modules = resolve(current, path, 'node_modules'); + const destination = join(snapshot, path, 'node_modules'); + if (!existsSync(modules) || existsSync(destination)) continue; + mkdirSync(dirname(destination), { recursive: true }); + symlinkSync(modules, destination, 'dir'); + } + const destination = join(snapshot, 'tools/quality'); + rmSync(destination, { recursive: true, force: true }); + mkdirSync(dirname(destination), { recursive: true }); + symlinkSync(templateDirectory, destination, 'dir'); + process.chdir(snapshot); + const historicalConfig = { + ...config, + duplicatePaths: config.duplicatePaths?.filter((path) => existsSync(path)), + }; + return analyze(historicalConfig); + } finally { + process.chdir(current); + rmSync(snapshot, { recursive: true, force: true }); + rmSync(archiveDirectory, { recursive: true, force: true }); + } +} diff --git a/tools/quality/lib/knip-reporter.mjs b/tools/quality/lib/knip-reporter.mjs new file mode 100644 index 0000000..87999ef --- /dev/null +++ b/tools/quality/lib/knip-reporter.mjs @@ -0,0 +1,42 @@ +import jsonReporter from '../node_modules/knip/dist/reporters/json.js'; + +/** Reject incomplete Knip graphs before emitting the pinned version's standard JSON report. */ +export default async function qualityReporter(options) { + if (options.hasConfigLoadErrors || options.counters.processed === 0) { + throw new Error( + 'Knip failed to load configuration or analyzed an empty graph', + ); + } + for (const required of [ + 'files', + 'exports', + 'dependencies', + 'unlisted', + 'unresolved', + ]) { + if (!options.report[required]) + throw new Error(`Mandatory Knip issue type disabled: ${required}`); + } + const incomplete = options.configurationHints.filter((hint) => + [ + 'entry-empty', + 'project-empty', + 'project-extension-unregistered', + 'project-extension-excluded', + 'workspace-unconfigured', + 'top-level-unconfigured', + 'ignore', + 'ignoreFiles', + 'ignoreBinaries', + 'ignoreDependencies', + 'ignoreUnresolved', + 'ignoreWorkspaces', + ].includes(hint.type), + ); + if (incomplete.length) { + throw new Error( + `Knip coverage/stale exclusion failure: ${incomplete.map((hint) => `${hint.type}:${hint.identifier}`).join(', ')}`, + ); + } + await jsonReporter(options); +} diff --git a/tools/quality/lib/reports.mjs b/tools/quality/lib/reports.mjs new file mode 100644 index 0000000..19c9a8e --- /dev/null +++ b/tools/quality/lib/reports.mjs @@ -0,0 +1,265 @@ +import { relative, isAbsolute } from 'node:path'; +import { existsSync } from 'node:fs'; +import ts from 'typescript'; +import { currentFile } from './git.mjs'; +import { digest, record } from './baseline.mjs'; + +/** Convert report paths to portable repository paths; external paths are not silently accepted. */ +export function repoPath(path) { + if (typeof path !== 'string' || !path) + throw new Error('Analyzer returned a missing file path'); + const normalized = (isAbsolute(path) ? relative(process.cwd(), path) : path) + .replaceAll('\\', '/') + .replace(/^\.\//, ''); + if (normalized === '..' || normalized.startsWith('../')) + throw new Error(`Analyzer escaped repository: ${path}`); + return normalized; +} + +/** Preserve all enabled Knip issue categories and distinguish separate symbols in the same file. */ +export function knipRecords(report) { + if (!report || !Array.isArray(report.issues)) + throw new Error('Invalid Knip JSON schema'); + const results = []; + for (const row of report.issues) { + const path = repoPath(row.file); + for (const [type, issues] of Object.entries(row)) { + if (['file', 'owners'].includes(type)) continue; + if (!Array.isArray(issues)) + throw new Error(`Invalid Knip category: ${type}`); + const grouped = new Map(); + for (const issue of issues) { + const symbols = (Array.isArray(issue) ? issue : [issue]).map( + (item) => item.name ?? item.symbol, + ); + if (symbols.some((symbol) => typeof symbol !== 'string')) + throw new Error(`Invalid Knip symbol: ${path}/${type}`); + const symbol = symbols.sort().join(','); + grouped.set(symbol, (grouped.get(symbol) ?? 0) + 1); + } + for (const [symbol, count] of grouped) + results.push( + record(`${path}|${type}|${symbol}`, count, { + path, + rule: type, + symbol, + }), + ); + } + } + return results.sort((a, b) => a.key.localeCompare(b.key)); +} + +/** Normalize token evidence without stripping string values or treating comments as meaningful duplicates. */ +export function tokenFingerprint(fragment) { + const scanner = ts.createScanner( + ts.ScriptTarget.Latest, + true, + ts.LanguageVariant.JSX, + fragment, + ); + const tokens = []; + for ( + let token = scanner.scan(); + token !== ts.SyntaxKind.EndOfFileToken; + token = scanner.scan() + ) { + tokens.push([token, scanner.getTokenText()]); + } + return digest(JSON.stringify(tokens)); +} + +/** Parse actual dependency-cruiser output; only pre-existing runtime cycles may be tracked as debt. */ +export function architectureRecords(report) { + if ( + !Array.isArray(report?.modules) || + !report.modules.length || + !report.summary?.totalCruised || + !Array.isArray(report.summary.violations) + ) + throw new Error('dependency-cruiser returned invalid/empty coverage'); + const cycles = new Map(); + for (const violation of report.summary.violations) { + if ( + violation.type !== 'cycle' || + violation.rule?.name !== 'no-runtime-cycles' || + !Array.isArray(violation.cycle) || + !violation.cycle.length + ) { + throw new Error( + `Non-baselinable architecture violation: ${violation.rule?.name}: ${violation.from} -> ${violation.to}`, + ); + } + const members = violation.cycle.map((member) => repoPath(member.name)); + const rotations = members.map((_, index) => + [...members.slice(index), ...members.slice(0, index)].join(' -> '), + ); + const key = `no-runtime-cycles|${rotations.sort()[0]}`; + cycles.set( + key, + record(key, 1, { + rule: 'no-runtime-cycles', + paths: [...new Set(members)].sort(), + }), + ); + } + return [...cycles.values()].sort((a, b) => a.key.localeCompare(b.key)); +} + +/** Resolve jscpd's embedded Svelte fragments to an existing source while retaining their language identity. */ +function duplicateSource(path) { + const participant = repoPath(path); + const embedded = + /^(.*\.svelte):(html|css|scss|sass|less|stylus|javascript|typescript|jsx|tsx)$/.exec( + participant, + ); + if (!embedded) { + if (/\.svelte:/.test(participant)) + throw new Error(`Unknown Svelte clone fragment: ${participant}`); + return { path: participant, participant, embedded: false }; + } + const source = embedded[1]; + if (!existsSync(source)) + throw new Error(`Missing Svelte clone source: ${source}`); + return { path: source, participant, embedded: true }; +} + +/** Identify clone groups by normalized code and participants, so unrelated unique code cannot dilute violations. */ +export function duplicateRecords(report) { + if ( + !report || + !Array.isArray(report.duplicates) || + !report.statistics?.total?.sources + ) { + throw new Error('jscpd report is missing or has empty source coverage'); + } + const grouped = new Map(); + for (const clone of report.duplicates) { + const first = duplicateSource(clone.firstFile?.name); + const second = duplicateSource(clone.secondFile?.name); + let fragment = clone.fragment; + if (typeof fragment !== 'string') { + if (first.embedded || second.embedded) + throw new Error('jscpd omitted embedded fragment evidence'); + const source = currentFile(first.path); + if ( + source === null || + !Number.isInteger(clone.firstFile.start) || + !Number.isInteger(clone.firstFile.end) + ) { + throw new Error('jscpd omitted clone evidence'); + } + fragment = source + .split(/\r?\n/) + .slice(clone.firstFile.start - 1, clone.firstFile.end) + .join('\n'); + } + const fingerprint = `${clone.format}|${tokenFingerprint(fragment)}`; + const group = grouped.get(fingerprint) ?? { + paths: new Set(), + participants: new Set(), + pairs: 0, + tokens: 0, + }; + group.paths.add(first.path); + group.paths.add(second.path); + group.participants.add(first.participant); + group.participants.add(second.participant); + group.pairs++; + group.tokens = Math.max(group.tokens, clone.tokens ?? 0); + grouped.set(fingerprint, group); + } + return [...grouped] + .map(([fingerprint, group]) => { + const paths = [...group.paths].sort(); + const participants = [...group.participants].sort(); + return record(`${fingerprint}|${participants.join('|')}`, group.pairs, { + paths, + ...(participants.some((path) => /\.svelte:/.test(path)) + ? { participants } + : {}), + tokens: group.tokens, + }); + }) + .sort((a, b) => a.key.localeCompare(b.key)); +} + +/** Locate the enclosing declaration for an ESLint diagnostic without using unstable line numbers as identity. */ +function scopeAt(source, line, column) { + const offset = source.getPositionOfLineAndCharacter( + Math.max(0, line - 1), + Math.max(0, column - 1), + ); + let scope = ''; + const visit = (node) => { + if (node.pos <= offset && node.end >= offset) { + if (ts.isFunctionLike(node)) + scope = + node.name?.getText(source) ?? + node.parent.name?.getText(source) ?? + ''; + ts.forEachChild(node, visit); + } + }; + visit(source); + return scope; +} + +/** Only complexity diagnostics may use a debt baseline; parser, typed and correctness errors remain fatal. */ +export function eslintRecords(report) { + if (!Array.isArray(report) || report.length === 0) + throw new Error('ESLint returned empty source coverage'); + const allowed = new Set([ + 'complexity', + 'max-depth', + 'max-params', + 'max-lines', + 'max-lines-per-function', + 'sonarjs/cognitive-complexity', + ]); + const results = []; + for (const file of report) { + const path = repoPath(file.filePath); + if (!Array.isArray(file.messages)) throw new Error('Invalid ESLint report'); + const source = ts.createSourceFile( + path, + currentFile(path) ?? '', + ts.ScriptTarget.Latest, + true, + ); + const occurrences = new Map(); + for (const message of file.messages) { + if (message.fatal || !allowed.has(message.ruleId)) { + throw new Error( + `${path}: non-baselinable ${message.ruleId ?? 'parser'}: ${message.message}`, + ); + } + const metricPatterns = { + complexity: /complexity of (\d+)/i, + 'max-depth': /(?:nested too deeply|maximum allowed).*?\((\d+)\)/i, + 'max-params': /too many parameters \((\d+)\)/i, + 'max-lines': /too many lines \((\d+)\)/i, + 'max-lines-per-function': /too many lines \((\d+)\)/i, + 'sonarjs/cognitive-complexity': /complexity from (\d+)/i, + }; + const values = metricPatterns[message.ruleId].exec(message.message); + if (!values) + throw new Error(`No metric in ESLint diagnostic: ${message.message}`); + const scope = + message.ruleId === 'max-lines' + ? '' + : scopeAt(source, message.line ?? 1, message.column ?? 1); + const identity = `${path}|${message.ruleId}|${scope}`; + const occurrence = occurrences.get(identity) ?? 0; + occurrences.set(identity, occurrence + 1); + results.push( + record(`${identity}|${occurrence}`, Number(values[1]), { + path, + rule: message.ruleId, + scope, + }), + ); + } + } + return results.sort((a, b) => a.key.localeCompare(b.key)); +} diff --git a/tools/quality/lib/template.mjs b/tools/quality/lib/template.mjs new file mode 100644 index 0000000..0a31562 --- /dev/null +++ b/tools/quality/lib/template.mjs @@ -0,0 +1,56 @@ +import { existsSync, readFileSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; +import { baseFile } from './git.mjs'; +import { digest } from './baseline.mjs'; + +/** Inventory all vendored files except installed dependencies; unexpected symlinks cannot hide source. */ +export function templateFiles(root, relative = '') { + return readdirSync(join(root, relative), { withFileTypes: true }) + .flatMap((entry) => { + const path = join(relative, entry.name).replaceAll('\\', '/'); + if (path === 'node_modules' || path === 'template-manifest.json') + return []; + if (entry.isSymbolicLink()) + throw new Error(`Untracked template symlink: ${path}`); + return entry.isDirectory() ? templateFiles(root, path) : [path]; + }) + .sort(); +} + +/** Keep the vendored exemption exact and require a new template version for changed preset contents. */ +export function verifyTemplate(base) { + const root = 'tools/quality'; + if (!existsSync(root)) return; // Standalone CLI fixtures exercise the runner outside a vendored checkout. + const manifestPath = `${root}/template-manifest.json`; + if (!existsSync(manifestPath)) + throw new Error( + 'Vendored quality template is missing its versioned inventory', + ); + const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); + const packageInfo = JSON.parse(readFileSync(`${root}/package.json`, 'utf8')); + if (manifest.schemaVersion !== 1 || manifest.version !== packageInfo.version) + throw new Error('Template version mismatch'); + const files = templateFiles(root); + if ( + JSON.stringify(files) !== JSON.stringify(Object.keys(manifest.files).sort()) + ) + throw new Error('Quality template has undeclared/missing files'); + for (const path of files) { + if ( + digest(readFileSync(`${root}/${path}`, 'utf8')) !== manifest.files[path] + ) + throw new Error(`Quality template integrity mismatch: ${path}`); + } + const previousText = baseFile(base, manifestPath); + if (previousText) { + const previous = JSON.parse(previousText); + if ( + previous.version === manifest.version && + JSON.stringify(previous.files) !== JSON.stringify(manifest.files) + ) { + throw new Error( + 'Quality template changed without an explicit version update', + ); + } + } +} diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json new file mode 100644 index 0000000..5b96b4b --- /dev/null +++ b/tools/quality/package-lock.json @@ -0,0 +1,6852 @@ +{ + "name": "@1msg/quality-template", + "version": "1.0.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@1msg/quality-template", + "version": "1.0.2", + "dependencies": { + "@eslint/js": "9.39.5", + "dependency-cruiser": "18.6.0", + "eslint": "9.39.5", + "eslint-import-resolver-typescript": "4.4.5", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-n": "18.4.1", + "eslint-plugin-perfectionist": "5.12.1", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-sonarjs": "3.0.7", + "eslint-plugin-unicorn": "62.0.0", + "globals": "17.13.0", + "husky": "9.1.7", + "jscpd": "5.4.1", + "knip": "6.41.0", + "lint-staged": "16.2.7", + "picomatch": "4.0.7", + "prettier": "3.9.10", + "typescript": "5.9.3", + "typescript-eslint": "8.71.1" + }, + "engines": { + "node": "24.x" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz", + "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz", + "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.9", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz", + "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.7.tgz", + "integrity": "sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==", + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.2", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", + "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@oxc-parser/binding-android-arm-eabi": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.153.0.tgz", + "integrity": "sha512-BcWu25dMwMjHpaDCEidmpAi7rGg1qZoihJeUUH9bD55pVZ0z4Wa5CQgqSTo0R41H81oozisQKW3WqvAN2m77IQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.153.0.tgz", + "integrity": "sha512-9l5rdp2DhRqVriBHsNpu5cEf+hizZ4B58rt93HzyQEBUgZiC6qe2oFpaAAnXGCxHGnQExI1s7S2G0QhFacUZ6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.153.0.tgz", + "integrity": "sha512-EcpsyRXHhENDpekpG4QNaSZj2F/BAz4Gh4o89zZwNss86R8KyRSQ6sXbAj74Xyeb4z3j/yBZZ6joQZhraIWyfw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.153.0.tgz", + "integrity": "sha512-hlj80HUQy07/2lYp6rmxH+3u+H2ik3rjLR52CUdPApxmZCNxASDUf/+ykTzAHS/fehftmVMATKvPaWmuLHuasg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.153.0.tgz", + "integrity": "sha512-fWRcv2pMSh1qtez46MOu8vuUJ5fiaQZPHSphbWulbL7SHBMKfRgZl2PzjXZYQJbq7NEXyXbgIuIuUm+/Rmkv8w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.153.0.tgz", + "integrity": "sha512-paZeUK1GXShl/bOJQET1/8AQxayFeuN4SIWAkgTRxE7ZQwv9uYSB2n0648smygP22N7jcI3zxAm0Z+ALNiIKxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.153.0.tgz", + "integrity": "sha512-qFPp5NwMf4K1C0O+DCVGmcbOaYyYAq98Rvv9p4VSfb777iUwlJCqMUxf6QG9N5f5ls4TEX6LitOZHi+6GL6rYQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.153.0.tgz", + "integrity": "sha512-oufEhZCX7saeo27Logra8cvBR1jQ/yw2zUI2hHmWw3qA/XYqEW31FOvLQBv7DWN32NjVdlcaP11WBBZTJo4k9g==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.153.0.tgz", + "integrity": "sha512-zXYzuAqng85h6+LI3iRm0zeMLX1/K2z41ZAMWxVRgt0D10VvZUaV5q+TEB46KDhoKBpdexoTLC6QoB/EiP2oqQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-ppc64-gnu": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.153.0.tgz", + "integrity": "sha512-J7+NLwLEzdkKM9cKyPHH/AjXXstWOs98KYgLrPPnO4N9MO8EZRBfPNnBcS3S67uMOBkRpUmCl2FhRnWdQ5CbBA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.153.0.tgz", + "integrity": "sha512-sD0K11GQTLWylln54nPMMTtgmBbQrR5It/vMpZpy/fogiw8O2AvIE+9LuWUXddrWk9zvFIHGRcSgFn4IHOfoYg==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-musl": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.153.0.tgz", + "integrity": "sha512-7L66uql2BhvSz51LwfExjOdn6et/ydTiQxl23VApdKzJhTc3TczA1Qt6VR/UcvlQrL2ZbytIJb447vh7p5wmUw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.153.0.tgz", + "integrity": "sha512-hXV3T7mNyrPR19rbPYkglkQJtoM/UNo/xwbZeeqdAxEg8PXgb4LXXuxPpGgI4bzRRCWwLUxdDSS58xIyC2u1TA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.153.0.tgz", + "integrity": "sha512-Da8Vqs1xdtoDYtEjmozD7wGgJeLBQkMbR0WUBECOSxodyX5DXy8ySlvJWbukyO2Q0+TM9EK+4LT6tbq0jCg4hQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.153.0.tgz", + "integrity": "sha512-zGAPxNTIIw6X5WyTRscIFE/oDjpdNtrrl32ing6NOXdGjzRucadnxBilexLdeYQ9YxixF93GujpXyQ0jw7ddSg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-openharmony-arm64": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.153.0.tgz", + "integrity": "sha512-GoHzpqP5XyPIp9DHokoEdCp+K4UPl/h1neFj1uXnUB3pJYyOQ7NOhFVOttNUgCGcj2eywAvu5cRivTOSq4S10g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.153.0.tgz", + "integrity": "sha512-xGcy12tO9k7zFbeyQzEuilfWfQpyRq23/fLPfN3wjSWuWv58k46fQT1hsO1KFNykZuVGW9xSJE/z592TmAoSDA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-ia32-msvc": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.153.0.tgz", + "integrity": "sha512-o1ykUjWncvXX6N5a4KebgLjtD8zRui+f1llMhSGoSC9oP2KOqapRpdwmZ3NcNG0axFouwVKmhGBjd+IhA8BksA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.153.0.tgz", + "integrity": "sha512-gxQz7G96Up136fd+2zWrP+o6FYGs9NO4Dyv55IoeJFJUDwLFHcLYY11hhA5wQKs0HoM57Q8esQ3nEVhnCdsjAQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.153.0.tgz", + "integrity": "sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@oxc-resolver/binding-android-arm-eabi": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.24.2.tgz", + "integrity": "sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@oxc-resolver/binding-android-arm64": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.24.2.tgz", + "integrity": "sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-arm64": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.24.2.tgz", + "integrity": "sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.24.2.tgz", + "integrity": "sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.24.2.tgz", + "integrity": "sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.24.2.tgz", + "integrity": "sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.24.2.tgz", + "integrity": "sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.24.2.tgz", + "integrity": "sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.24.2.tgz", + "integrity": "sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.24.2.tgz", + "integrity": "sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.24.2.tgz", + "integrity": "sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-musl": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.24.2.tgz", + "integrity": "sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.24.2.tgz", + "integrity": "sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.24.2.tgz", + "integrity": "sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.24.2.tgz", + "integrity": "sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-openharmony-arm64": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.24.2.tgz", + "integrity": "sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.24.2.tgz", + "integrity": "sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.2", + "@emnapi/runtime": "1.11.2", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.24.2.tgz", + "integrity": "sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.24.2.tgz", + "integrity": "sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", + "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.1.tgz", + "integrity": "sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.71.1", + "@typescript-eslint/type-utils": "8.71.1", + "@typescript-eslint/utils": "8.71.1", + "@typescript-eslint/visitor-keys": "8.71.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.71.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.1.tgz", + "integrity": "sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.71.1", + "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/typescript-estree": "8.71.1", + "@typescript-eslint/visitor-keys": "8.71.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.1.tgz", + "integrity": "sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.71.1", + "@typescript-eslint/types": "^8.71.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.1.tgz", + "integrity": "sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/visitor-keys": "8.71.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.1.tgz", + "integrity": "sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.1.tgz", + "integrity": "sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/typescript-estree": "8.71.1", + "@typescript-eslint/utils": "8.71.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.1.tgz", + "integrity": "sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.1.tgz", + "integrity": "sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.71.1", + "@typescript-eslint/tsconfig-utils": "8.71.1", + "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/visitor-keys": "8.71.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.1.tgz", + "integrity": "sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.71.1", + "@typescript-eslint/types": "8.71.1", + "@typescript-eslint/typescript-estree": "8.71.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.1.tgz", + "integrity": "sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.71.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-jsx-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/acorn-jsx-walk/-/acorn-jsx-walk-2.0.0.tgz", + "integrity": "sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==", + "license": "MIT" + }, + "node_modules/acorn-loose": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.5.2.tgz", + "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.4.0.tgz", + "integrity": "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.2.0.tgz", + "integrity": "sha512-VXY5eFRarnXcYxwBjJzPmEhH55+rmP79/+ueDhi0F+TuqfHCItagIHqxeUZrmgrOPa31QTh9H85DjX3FfJ0FTg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "es-shim-unscopables": "^1.1.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.28", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.28.tgz", + "integrity": "sha512-br0LOmjJqr6Rt4AEkadbcNf67Zpo7EPwKsWbjnRrJIa1QYFHQBqM4C7F2WTbV8ahTEcg1Eo+Y0aWjjORInYFyA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001815", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001815.tgz", + "integrity": "sha512-uDybUEyfgbyJJ93J1vikTylBX31AkdVYeVPeffMQpf8XN7hSfr0oZOn4VFOIMNvtU5+rHvC5Udg2TgtJKHm23Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.7" + }, + "engines": { + "node": ">=6.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dependency-cruiser": { + "version": "18.6.0", + "resolved": "https://registry.npmjs.org/dependency-cruiser/-/dependency-cruiser-18.6.0.tgz", + "integrity": "sha512-It7NW5AmCDBCLMq7I91Nfu8VRKzrIE6S+M/FMQzALDceJ0B1PWRHo77q9YJg/HwyBBEWHVtOuTptIQki+xecOw==", + "license": "MIT", + "dependencies": { + "acorn": "8.19.0", + "acorn-jsx": "5.3.2", + "acorn-jsx-walk": "2.0.0", + "acorn-loose": "8.5.2", + "acorn-walk": "8.3.5", + "commander": "15.0.0", + "enhanced-resolve": "5.26.0", + "ignore": "7.0.12", + "interpret": "3.1.1", + "is-installed-globally": "1.0.1", + "json5": "2.2.3", + "picomatch": "4.0.7", + "prompts": "2.4.2", + "rechoir": "0.8.0", + "safe-regex": "2.1.1", + "semver": "7.8.5", + "tsconfig-paths-webpack-plugin": "4.2.0", + "watskeburt": "6.0.0" + }, + "bin": { + "depcruise": "bin/dependency-cruiser.mjs", + "depcruise-baseline": "bin/depcruise-baseline.mjs", + "depcruise-fmt": "bin/depcruise-fmt.mjs", + "depcruise-wrap-stream-in-html": "bin/wrap-stream-in-html.mjs", + "dependency-cruise": "bin/dependency-cruiser.mjs", + "dependency-cruiser": "bin/dependency-cruiser.mjs" + }, + "engines": { + "node": "^22||^24||>=26" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.452", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.452.tgz", + "integrity": "sha512-cVvk1YBSj6571VmV6hdJTqj94Y79xSu8cj6Y9t6ae4Y4431z8/7EJFvu3rVp90xhfuv9BpPKUmaLfTo4+FOGBg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", + "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.5.tgz", + "integrity": "sha512-nbE5XLph6TLtGYcu/U6e6ZVXyKBhbDWK5cLGk76eJ7NdZpwf1P9EFkpt1Z01mNZNrrilsAYWKH6zUkL4reoXbw==", + "license": "ISC", + "dependencies": { + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^16.17.0 || >=18.6.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-n": { + "version": "18.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-18.4.1.tgz", + "integrity": "sha512-2sBReWOvCbzgkPri9M5SFmD5EbIwZLa1xz6B5RZsrI19WSFKpyx1sOMr+pdk8puCiXuEgCbErEHy1PuaUrc/4w==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "globrex": "^0.1.2", + "ignore": "^5.3.2", + "js-yaml": "^5.4.1", + "semver": "^7.6.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.57.1", + "ts-declaration-location": "^1.0.6", + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "ts-declaration-location": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-n/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint-plugin-n/node_modules/js-yaml": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.3.tgz", + "integrity": "sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.mjs" + } + }, + "node_modules/eslint-plugin-perfectionist": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.12.1.tgz", + "integrity": "sha512-krdSE7Dz+TCtcVr2+rfNhlOIFFBJcUdoRvjaN7JQnsaVnxJw+BZh9wMkY3MSLCJat+yW+UPTQLKS82Epc7MGZA==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.70.0", + "@typescript-eslint/utils": "^8.70.0", + "natural-orderby": "^5.0.0" + }, + "engines": { + "node": "^20.0.0 || >=22.0.0" + }, + "peerDependencies": { + "eslint": "^8.45.0 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-sonarjs": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-3.0.7.tgz", + "integrity": "sha512-62jB20krIPvcwBLAyG3VVKa2ce2j2lL1yCb8Y0ylMRR/dLvCCTiQx8gQbXb+G81k1alPZ2/I3muZinqWQdBbzw==", + "license": "LGPL-3.0-only", + "dependencies": { + "@eslint-community/regexpp": "4.12.2", + "builtin-modules": "3.3.0", + "bytes": "3.1.2", + "functional-red-black-tree": "1.0.1", + "jsx-ast-utils-x": "0.1.0", + "lodash.merge": "4.6.2", + "minimatch": "10.1.2", + "scslre": "0.3.0", + "semver": "7.7.4", + "typescript": ">=5" + }, + "peerDependencies": { + "eslint": "^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-sonarjs/node_modules/minimatch": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", + "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-plugin-sonarjs/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "62.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-62.0.0.tgz", + "integrity": "sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "@eslint-community/eslint-utils": "^4.9.0", + "@eslint/plugin-kit": "^0.4.0", + "change-case": "^5.4.4", + "ci-info": "^4.3.1", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.46.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.4.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", + "pluralize": "^8.0.0", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.13.0", + "semver": "^7.7.3", + "strip-indent": "^4.1.1" + }, + "engines": { + "node": "^20.10.0 || >=21.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=9.38.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" + }, + "node_modules/fd-package-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-2.0.0.tgz", + "integrity": "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==", + "license": "MIT", + "dependencies": { + "walk-up-path": "^4.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/formatly": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/formatly/-/formatly-0.11.4.tgz", + "integrity": "sha512-TeCC10lP8KCgoX+Fe5lryILIT0/Dy+nP0OSVnsuB5CwXoLuOdqxCYlPFF1inR8S/zTy1ec7TjhS2TeRKWzzImA==", + "license": "MIT", + "dependencies": { + "fd-package-json": "^2.0.0", + "package-manager-detector": "^1.8.0" + }, + "bin": { + "formatly": "bin/index.mjs" + }, + "engines": { + "node": ">=18.14.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "license": "MIT" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.7.0.tgz", + "integrity": "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "17.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz", + "integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ignore": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", + "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-builtin-module": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", + "license": "MIT", + "dependencies": { + "builtin-modules": "^5.0.0" + }, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-builtin-module/node_modules/builtin-modules": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.4.0.tgz", + "integrity": "sha512-JCWSCdun+4Ovd9BhM/Vtlmwb7oD6Wl4YiPRXXwhAuwlPhW1un/MKgXn7GZoFm53ginnoNzus69V8JWx0K393jg==", + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.1.tgz", + "integrity": "sha512-li88H4QGRoNMX27jEmY8nR515oJVspAgC/WFMlhHfFV8RJ4QyGpHhXnwAe9gH5RIgKmdYRUmrOhQobcgEjIdSw==", + "license": "MIT", + "dependencies": { + "global-directory": "^4.0.1", + "is-path-inside": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscpd": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd/-/jscpd-5.4.1.tgz", + "integrity": "sha512-afUt+LSQMmzSPYrWZlNGTwj8X4tmwVJbMNmr92qxPf4uUF/naLwG7SQyMPEZtrHqGgzGxmAzNjiwlVdjls2MyQ==", + "license": "MIT", + "bin": { + "jscpd": "run-jscpd.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://opencollective.com/jscpd" + }, + "optionalDependencies": { + "jscpd-darwin-arm64": "5.4.1", + "jscpd-darwin-x64": "5.4.1", + "jscpd-linux-arm64-gnu": "5.4.1", + "jscpd-linux-arm64-musl": "5.4.1", + "jscpd-linux-x64-gnu": "5.4.1", + "jscpd-linux-x64-musl": "5.4.1", + "jscpd-windows-arm64-msvc": "5.4.1", + "jscpd-windows-x64-msvc": "5.4.1" + } + }, + "node_modules/jscpd-darwin-arm64": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-darwin-arm64/-/jscpd-darwin-arm64-5.4.1.tgz", + "integrity": "sha512-LXHVeH60C9BsozcVIMPmXWvj97KqFKbCJYmYG4hDwfwIwS1kz+uF7yiObckP6h2xo12pD88nI4XjWTB5frjZUw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/jscpd-darwin-x64": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-darwin-x64/-/jscpd-darwin-x64-5.4.1.tgz", + "integrity": "sha512-Gqck4tcMZjv4IvYHU2Vcikb885zTADo5T/YfEqeu1i5W5tfFpLdViiTYrh5wbrW+uxBqC33gHpG1hy0xbGYknQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/jscpd-linux-arm64-gnu": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-linux-arm64-gnu/-/jscpd-linux-arm64-gnu-5.4.1.tgz", + "integrity": "sha512-XUYZJZVxSY7JIBEoyOOMTgvJwmymkns4wG55tu6I/vRKXnS5QtaTESQfRLt6xj1+62aflAvr01FAhPAy+du6tA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jscpd-linux-arm64-musl": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-linux-arm64-musl/-/jscpd-linux-arm64-musl-5.4.1.tgz", + "integrity": "sha512-h2sH8Bk++yBxWqq2QAy4fvPzXkw1vecDSyOmzLwPfnRQoQ2Q/EWxCNOrgJSb+SNMLWoHLLzfqx8m9wt2GG6a8w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jscpd-linux-x64-gnu": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-linux-x64-gnu/-/jscpd-linux-x64-gnu-5.4.1.tgz", + "integrity": "sha512-UiC4YoGAVVLy6hPVz8A6cndo7W5br4FAO2hADnFeinhBPnXPu0QFh1q/s/8B3ldeQHQkpYd/l5cjqNBMrbm78w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jscpd-linux-x64-musl": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-linux-x64-musl/-/jscpd-linux-x64-musl-5.4.1.tgz", + "integrity": "sha512-toAafl5roqfFotPrDJNMY9noNVZ9dReBqcO/nT5pJ8+7aq+opbscaLUcV4+8jxTq5btUD6CiO72+Fu+TyUZv3Q==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jscpd-windows-arm64-msvc": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-windows-arm64-msvc/-/jscpd-windows-arm64-msvc-5.4.1.tgz", + "integrity": "sha512-JLMga/NIwv/OPurPsXA2/d5OdWfdwrsBk2D4NhyKnrV/uNjo1BIi2zXztzDyTQVKMK/TEK6GPgLD143GG1fZ0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/jscpd-windows-x64-msvc": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/jscpd-windows-x64-msvc/-/jscpd-windows-x64-msvc-5.4.1.tgz", + "integrity": "sha512-sN57Y9YP3ijrqc1IsWDceOFHUwbukg9/mU2NSDHTryKKc5CUvWz+o9GId8uKTiJIhkKfR/Ce5GKkCepTwB6kaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jsx-ast-utils-x": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils-x/-/jsx-ast-utils-x-0.1.0.tgz", + "integrity": "sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/knip": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/knip/-/knip-6.41.0.tgz", + "integrity": "sha512-DrhQlIuV6xScd5Q+WTF1znd1w41QzxFGCtAHXCajsH/ndGMotHoNYbdXbuFtzW3mIOmniHtZ7zCtvnQkUmJtQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/webpro" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/knip" + } + ], + "license": "ISC", + "dependencies": { + "formatly": "^0.11.4", + "get-tsconfig": "4.14.3", + "jiti": "^2.7.0", + "oxc-parser": "^0.153.0", + "oxc-resolver": "11.24.2", + "picomatch": "^4.0.7", + "smol-toml": "^1.9.0", + "strip-json-comments": "5.0.3", + "tinyglobby": "^0.2.17", + "unbash": "^5.0.0", + "yaml": "^2.9.1", + "zod": "^4.6.5" + }, + "bin": { + "knip": "bin/knip.js", + "knip-bun": "bin/knip-bun.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/knip/node_modules/strip-json-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", + "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lint-staged": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", + "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "license": "MIT", + "dependencies": { + "commander": "^14.0.2", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "nano-spawn": "^2.0.0", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nano-spawn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.1.0.tgz", + "integrity": "sha512-yTW+2okrElHiH4fsiz/+/zc0EDo9BDDoC3iKk8dpv1GeRc9nUWzUZHx6TofMWErchhUQR8hY9/Eu1Uja9x1nqA==", + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" + }, + "node_modules/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.58", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.58.tgz", + "integrity": "sha512-BdiKAgbfRlvfMq/XzO/AF9NPmaA8a+YpLAyAFTVFBj3gARrAIfWvNq7Q7NE4se3KgFu0KkrvQMxTS0XVnsGzHg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/oxc-parser": { + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.153.0.tgz", + "integrity": "sha512-cEnpyyV1OJRXv++SFNw0z8i+2o/cr88rVLaOYJafELDoHM5yHvCAbwGRLvxuany6SNLcbblSMUyZaGzH+quSYg==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.153.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/oxc-project" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm-eabi": "0.153.0", + "@oxc-parser/binding-android-arm64": "0.153.0", + "@oxc-parser/binding-darwin-arm64": "0.153.0", + "@oxc-parser/binding-darwin-x64": "0.153.0", + "@oxc-parser/binding-freebsd-x64": "0.153.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.153.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.153.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.153.0", + "@oxc-parser/binding-linux-arm64-musl": "0.153.0", + "@oxc-parser/binding-linux-ppc64-gnu": "0.153.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.153.0", + "@oxc-parser/binding-linux-riscv64-musl": "0.153.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.153.0", + "@oxc-parser/binding-linux-x64-gnu": "0.153.0", + "@oxc-parser/binding-linux-x64-musl": "0.153.0", + "@oxc-parser/binding-openharmony-arm64": "0.153.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.153.0", + "@oxc-parser/binding-win32-ia32-msvc": "0.153.0", + "@oxc-parser/binding-win32-x64-msvc": "0.153.0" + } + }, + "node_modules/oxc-resolver": { + "version": "11.24.2", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.24.2.tgz", + "integrity": "sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-resolver/binding-android-arm-eabi": "11.24.2", + "@oxc-resolver/binding-android-arm64": "11.24.2", + "@oxc-resolver/binding-darwin-arm64": "11.24.2", + "@oxc-resolver/binding-darwin-x64": "11.24.2", + "@oxc-resolver/binding-freebsd-x64": "11.24.2", + "@oxc-resolver/binding-linux-arm-gnueabihf": "11.24.2", + "@oxc-resolver/binding-linux-arm-musleabihf": "11.24.2", + "@oxc-resolver/binding-linux-arm64-gnu": "11.24.2", + "@oxc-resolver/binding-linux-arm64-musl": "11.24.2", + "@oxc-resolver/binding-linux-ppc64-gnu": "11.24.2", + "@oxc-resolver/binding-linux-riscv64-gnu": "11.24.2", + "@oxc-resolver/binding-linux-riscv64-musl": "11.24.2", + "@oxc-resolver/binding-linux-s390x-gnu": "11.24.2", + "@oxc-resolver/binding-linux-x64-gnu": "11.24.2", + "@oxc-resolver/binding-linux-x64-musl": "11.24.2", + "@oxc-resolver/binding-openharmony-arm64": "11.24.2", + "@oxc-resolver/binding-wasm32-wasi": "11.24.2", + "@oxc-resolver/binding-win32-arm64-msvc": "11.24.2", + "@oxc-resolver/binding-win32-x64-msvc": "11.24.2" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz", + "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==", + "license": "MIT" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.1.tgz", + "integrity": "sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==", + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rechoir/node_modules/resolve": { + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/refa": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz", + "integrity": "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp-ast-analysis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz", + "integrity": "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.1" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regjsparser": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.4.tgz", + "integrity": "sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "license": "MIT", + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scslre": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz", + "integrity": "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.0", + "regexp-ast-analysis": "^0.7.0" + }, + "engines": { + "node": "^14.0.0 || >=16.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/smol-toml": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.1.tgz", + "integrity": "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.1.0.tgz", + "integrity": "sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "get-intrinsic": "^1.3.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.4", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.5.tgz", + "integrity": "sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.71.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.1.tgz", + "integrity": "sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.71.1", + "@typescript-eslint/parser": "8.71.1", + "@typescript-eslint/typescript-estree": "8.71.1", + "@typescript-eslint/utils": "8.71.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbash": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unbash/-/unbash-5.0.0.tgz", + "integrity": "sha512-RYNm/ISFtflWpIcXTPHHLJZ0mqzInav+L9ke9PcL+hHsSf9+Fd/syPb614Mlqs/O3AYgjnvxDOFl0a+zVqi1/w==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/watskeburt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/watskeburt/-/watskeburt-6.0.0.tgz", + "integrity": "sha512-jfiuDABaxSkC71T6oZ3vCS99roYkSHm/+As+G0Dz8taAHQb+SJBvLEm5RlsgG71XdfAj3rv7eudUBTgwcQUPlQ==", + "license": "MIT", + "bin": { + "watskeburt": "dist/run-cli.js" + }, + "engines": { + "node": "^22.13||^24||>=26" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", + "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.6.tgz", + "integrity": "sha512-4UmzQUF5fxvfcYHlbjBmejU+w+hbDnWFx4aS8kBx7nPBHcO2SqPbpAG8snbdg+Xse4pRefR98hgjFgIMCI/UhA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/tools/quality/package.json b/tools/quality/package.json new file mode 100644 index 0000000..62d20c2 --- /dev/null +++ b/tools/quality/package.json @@ -0,0 +1,34 @@ +{ + "name": "@1msg/quality-template", + "version": "1.0.2", + "private": true, + "type": "module", + "engines": { + "node": "24.x" + }, + "scripts": { + "test": "node --test test/*.test.mjs" + }, + "dependencies": { + "@eslint/js": "9.39.5", + "dependency-cruiser": "18.6.0", + "eslint": "9.39.5", + "eslint-import-resolver-typescript": "4.4.5", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-n": "18.4.1", + "eslint-plugin-perfectionist": "5.12.1", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-sonarjs": "3.0.7", + "eslint-plugin-unicorn": "62.0.0", + "globals": "17.13.0", + "husky": "9.1.7", + "jscpd": "5.4.1", + "knip": "6.41.0", + "lint-staged": "16.2.7", + "picomatch": "4.0.7", + "prettier": "3.9.10", + "typescript": "5.9.3", + "typescript-eslint": "8.71.1" + } +} diff --git a/tools/quality/prettier.config.mjs b/tools/quality/prettier.config.mjs new file mode 100644 index 0000000..9d0c3e3 --- /dev/null +++ b/tools/quality/prettier.config.mjs @@ -0,0 +1,2 @@ +/** One formatting policy shared by authored code and the quality template itself. */ +export default { singleQuote: true, trailingComma: 'all' }; diff --git a/tools/quality/run.mjs b/tools/quality/run.mjs new file mode 100644 index 0000000..e0b21ae --- /dev/null +++ b/tools/quality/run.mjs @@ -0,0 +1,360 @@ +#!/usr/bin/env node +import { + readFileSync, + writeFileSync, + mkdirSync, + mkdtempSync, + rmSync, +} from 'node:fs'; +import { dirname, resolve, join } from 'node:path'; +import { tmpdir } from 'node:os'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { + execute, + baseRef, + baseFile, + currentFile, + git, + changedFiles, +} from './lib/git.mjs'; +import { assess, parseJson } from './lib/baseline.mjs'; +import { runGuards, validateConfig } from './lib/guards.mjs'; +import { + knipRecords, + duplicateRecords, + eslintRecords, + architectureRecords, + tokenFingerprint, +} from './lib/reports.mjs'; +import { historicalAnalysis } from './lib/historical.mjs'; + +const directory = dirname(fileURLToPath(import.meta.url)); +const args = process.argv.slice(2); +const action = args[0]; + +/** Read an option without treating subsequent flags as values. */ +function option(name, fallback) { + const position = args.indexOf(name); + if (position < 0) return fallback; + const value = args[position + 1]; + if (!value || value.startsWith('--')) + throw new Error(`Missing value for ${name}`); + return value; +} + +/** Record analyzer exit state together with the report; non-diagnostic exits always fail. */ +function analyze(command, argv, name) { + const result = execute(command, argv); + if (![0, 1].includes(result.status)) + throw new Error(`${name} failed (${result.status}): ${result.stderr}`); + if (result.stderr.trim()) process.stderr.write(result.stderr); + return { status: result.status, report: parseJson(result.stdout, name) }; +} + +/** Run Knip's actual production or full graph with its independent config and JSON reporter. */ +function unused(config, production) { + const argv = [ + join(directory, 'node_modules/knip/bin/knip.js'), + '--config', + config.knipConfig ?? 'knip.json', + '--reporter', + join(directory, 'lib/knip-reporter.mjs'), + ]; + if (production) argv.push('--production'); + const { report } = analyze(process.execPath, argv, 'Knip'); + return { findings: knipRecords(report), report }; +} + +/** Run duplicate analysis into a fresh temporary directory, rejecting empty or missing output. */ +function duplicates(config) { + if (!config.duplicatePaths?.length) + throw new Error('duplicatePaths must list authored runtime/tooling roots'); + const output = mkdtempSync(join(tmpdir(), '1msg-jscpd-')); + try { + const argv = [ + join(directory, 'node_modules/jscpd/run-jscpd.js'), + ...config.duplicatePaths, + '--reporters', + 'json', + '--output', + output, + '--mode', + 'mild', + '--min-lines', + '5', + '--min-tokens', + '50', + '--silent', + '--absolute', + '--format', + ( + config.duplicateFormats ?? [ + 'javascript', + 'typescript', + 'jsx', + 'tsx', + 'svelte', + ] + ).join(','), + ]; + if (config.duplicateIgnore?.length) + argv.push('--ignore', config.duplicateIgnore.join(',')); + const result = execute(process.execPath, argv); + if (result.status !== 0) + throw new Error( + `jscpd failed (${result.status}): ${result.stderr || result.stdout}`, + ); + const report = parseJson( + readFileSync(join(output, 'jscpd-report.json'), 'utf8'), + 'jscpd', + ); + return { findings: duplicateRecords(report), report }; + } finally { + rmSync(output, { recursive: true, force: true }); + } +} + +/** Confirm initial allowances describe existing source; freshly introduced problems cannot be bootstrapped. */ +function initialEvidence(finding, base, historical) { + const prior = historical.find((item) => item.key === finding.key); + if (!prior || finding.value > prior.value) + throw new Error(`Cannot baseline a new/increased finding: ${finding.key}`); + const evidence = {}; + for (const path of finding.paths ?? [finding.path]) { + if (!path) throw new Error(`Finding lacks source evidence: ${finding.key}`); + const before = baseFile(base, path); + const current = currentFile(path); + if (before === null || current === null) + throw new Error(`Cannot baseline a new/missing file: ${path}`); + if (path.endsWith('package.json') && finding.symbol) { + const old = JSON.parse(before); + const dependencies = { + ...old.dependencies, + ...old.devDependencies, + ...old.optionalDependencies, + }; + evidence[path] = + finding.symbol in dependencies + ? `dependency:${finding.symbol}:${dependencies[finding.symbol]}` + : tokenFingerprint(before); + } else { + evidence[path] = tokenFingerprint(before); + } + } + return evidence; +} + +/** Write explicit historical allowances locally, then validate the same artifact as CI. */ +function bootstrap(findings, path, base, historical) { + if (process.env.CI) throw new Error('Baseline bootstrap is forbidden in CI'); + const owner = option('--owner'); + const expires = option('--expires'); + const reason = option('--reason'); + const issue = option('--issue'); + if (!owner || !expires || !reason || !issue) + throw new Error( + 'Bootstrap requires --owner, --expires, --reason and --issue', + ); + const entries = findings.map((finding) => ({ + ...finding, + owner, + expires, + reason, + issue, + evidence: initialEvidence(finding, base, historical), + })); + const baseline = { schemaVersion: 1, adoptionBase: base, entries }; + mkdirSync(dirname(path), { recursive: true }); + writeFileSync(path, `${JSON.stringify(baseline, null, 2)}\n`); + return baseline; +} + +/** Ratchet individual debt against trusted Git history, including reductions and expired allowances. */ +function gate(config, name, result, base, analyzeBase) { + if (!/^[a-z][a-z0-9-]*$/.test(name)) throw new Error('Invalid gate name'); + const path = `${config.baselineDir ?? 'quality/baselines'}/${name}.json`; + const raw = currentFile(path); + const old = baseFile(base, path); + const previous = old === null ? null : parseJson(old, 'trusted baseline'); + const historical = + previous || result.findings.length === 0 + ? [] + : historicalAnalysis(base, config, directory, analyzeBase).findings; + const baseline = args.includes('--bootstrap') + ? bootstrap(result.findings, path, base, historical) + : raw === null + ? { schemaVersion: 1, entries: [] } + : parseJson(raw, 'baseline'); + if (!previous && baseline.entries.length) { + if (baseline.adoptionBase !== base) + throw new Error('Initial baseline is not tied to the trusted base SHA'); + for (const entry of baseline.entries) { + if ( + JSON.stringify(entry.evidence) !== + JSON.stringify(initialEvidence(entry, base, historical)) + ) { + throw new Error(`Initial baseline evidence changed: ${entry.key}`); + } + } + } + const errors = assess(result.findings, baseline, previous); + if (name === 'duplicates') { + if ( + !Number.isFinite(config.duplicateMaxPercentage) || + config.duplicateMaxPercentage < 0 || + config.duplicateMaxPercentage > 100 + ) { + throw new Error( + 'duplicateMaxPercentage must specify the inventoried numeric ceiling (0–100)', + ); + } + const percentage = result.report.statistics.total.percentage; + if (!Number.isFinite(percentage)) + throw new Error('jscpd omitted its numeric duplicate percentage'); + if (percentage > config.duplicateMaxPercentage) + errors.push( + `Duplicate percentage ${percentage} exceeds ${config.duplicateMaxPercentage}`, + ); + } + mkdirSync('quality/reports', { recursive: true }); + writeFileSync( + `quality/reports/${name}.json`, + `${JSON.stringify( + { + schemaVersion: 1, + head: git(['rev-parse', 'HEAD']).trim(), + base, + result: errors.length ? 'FAIL' : 'PASS', + findings: result.findings, + errors, + analyzer: result.report, + }, + null, + 2, + )}\n`, + ); + if (errors.length) throw new Error(errors.join('\n')); + console.log( + `${name}: PASS (${result.findings.length} existing, individually tracked violations)`, + ); +} + +/** Dispatch one mandatory check; unsupported actions or missing configuration never count as success. */ +async function main() { + const config = ( + await import(pathToFileURL(resolve('quality.config.mjs')).href) + ).default; + validateConfig(config); + const base = baseRef( + config.defaultBranch, + option('--base', process.env.QUALITY_BASE), + ); + if (action === 'changed-files') { + console.log(JSON.stringify(changedFiles(base))); + return; + } + if (action === 'guards') { + const result = runGuards(config, base); + if (result.errors.length) throw new Error(result.errors.join('\n')); + console.log( + `guards: PASS (${result.checked} authored source files inventoried)`, + ); + return; + } + if (['unused-production', 'unused-full'].includes(action)) { + const analyzeBase = (sourceConfig) => + unused(sourceConfig, action === 'unused-production'); + gate(config, action, analyzeBase(config), base, analyzeBase); + return; + } + if (action === 'duplicates') { + gate(config, action, duplicates(config), base, duplicates); + return; + } + if (action === 'duplicates-full') { + if (!config.duplicateFullPaths?.length) + throw new Error( + 'duplicateFullPaths must inventory runtime, tests and tooling', + ); + const result = duplicates({ + ...config, + duplicatePaths: config.duplicateFullPaths, + duplicateIgnore: + config.duplicateFullIgnore ?? + (config.generated ?? []).map((entry) => entry.pattern), + }); + mkdirSync('quality/reports', { recursive: true }); + writeFileSync( + 'quality/reports/duplicates-full.json', + `${JSON.stringify( + { + schemaVersion: 1, + head: git(['rev-parse', 'HEAD']).trim(), + base, + result: 'REPORT', + ...result, + }, + null, + 2, + )}\n`, + ); + console.log( + `duplicates-full: analyzed ${result.report.statistics.total.sources} files; report saved`, + ); + return; + } + if (action === 'report' && option('--kind') === 'eslint') { + const split = args.indexOf('--'); + if (split < 0 || !args[split + 1]) + throw new Error('report requires -- '); + const analyzeBase = () => { + const { report } = analyze( + args[split + 1], + args.slice(split + 2), + 'ESLint', + ); + return { findings: eslintRecords(report), report }; + }; + gate( + config, + option('--name', 'complexity'), + analyzeBase(), + base, + analyzeBase, + ); + return; + } + if (action === 'report' && option('--kind') === 'depcruiser') { + const split = args.indexOf('--'); + if (split < 0 || !args[split + 1]) + throw new Error('report requires -- '); + const analyzeBase = () => { + const result = execute(args[split + 1], args.slice(split + 2)); + const report = parseJson(result.stdout, 'dependency-cruiser'); + if ( + !Number.isInteger(report.summary?.advisedExitCode) || + (result.status !== 0 && + result.status !== report.summary.advisedExitCode % 256) + ) { + throw new Error( + `dependency-cruiser exit/report mismatch (${result.status}): ${result.stderr}`, + ); + } + return { findings: architectureRecords(report), report }; + }; + gate( + config, + option('--name', 'architecture'), + analyzeBase(), + base, + analyzeBase, + ); + return; + } + throw new Error(`Unknown quality action: ${action}`); +} + +main().catch((error) => { + console.error(error.message); + process.exitCode = 1; +}); diff --git a/tools/quality/seal.mjs b/tools/quality/seal.mjs new file mode 100644 index 0000000..8e2c5b9 --- /dev/null +++ b/tools/quality/seal.mjs @@ -0,0 +1,19 @@ +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { digest } from './lib/baseline.mjs'; +import { templateFiles } from './lib/template.mjs'; + +// Maintainers seal a reviewed template version before copying it into consumer repositories. +const root = dirname(fileURLToPath(import.meta.url)); +const { version } = JSON.parse(readFileSync(`${root}/package.json`, 'utf8')); +const files = Object.fromEntries( + templateFiles(root).map((path) => [ + path, + digest(readFileSync(`${root}/${path}`, 'utf8')), + ]), +); +writeFileSync( + `${root}/template-manifest.json`, + `${JSON.stringify({ schemaVersion: 1, version, files }, null, 2)}\n`, +); diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json new file mode 100644 index 0000000..444e17d --- /dev/null +++ b/tools/quality/template-manifest.json @@ -0,0 +1,25 @@ +{ + "schemaVersion": 1, + "version": "1.0.2", + "files": { + "README.md": "1d3f6f9d420adea402d92aff483c14271e6e24c291437d6ea5b59c3162702a20", + "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", + "lib/baseline.mjs": "7876ba90b80448d9c9003c21e348095ed22630c41fc26ed944984742020549dd", + "lib/git.mjs": "b7c26871526d864bf8d12f01c613d3bfa0adb2da9d072544d8f09407ef598758", + "lib/guards.mjs": "310c224c5d072fa16b1cf5f0c47e5da4258f0f63fa9a1c4dc114c9fe192bc398", + "lib/historical.mjs": "d338d88bae6d1da19f27296fbb6c57cff4ca09664fe7baa8d6c8d801ca3e69f2", + "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", + "lib/reports.mjs": "f47f6cbf8022691e61a245bf54a5fdd1ba9f2037906ec6576f2ac771224161dc", + "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", + "package-lock.json": "931d28ffff6590892a072569df9c57345d0a388a22598b3482dee53136a52828", + "package.json": "b2c70073c423135e4b5abba9507d58fd5136a676339e816b72d6dd4bcbb1b757", + "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", + "run.mjs": "b60c0fc2419c8cfd32eddf369da38b2d87e2b7eacbc31fda31c598930900f199", + "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", + "test/cli.test.mjs": "f743a18f0763cf5b5f42f8d2a4b71f67a4de900a3955a299309395af95b99cf3", + "test/ratchet.test.mjs": "62fef1cc7a1851db81c30966909968ff84637b8ed8003821120269c4fae70d49", + "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", + "tsconfig.node.json": "627661abcb7e992c4bfaf98d6e68a12678573b5d4f6e821ea0fa43fa6e233f28", + "tsconfig.svelte.json": "5777247ea98aaf2d886b87cd12206a641377edcdd086ce5fd5b58adc6f0bc771" + } +} diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs new file mode 100644 index 0000000..897d9cd --- /dev/null +++ b/tools/quality/test/cli.test.mjs @@ -0,0 +1,510 @@ +import { templateFiles } from '../lib/template.mjs'; +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { + mkdtempSync, + mkdirSync, + writeFileSync, + rmSync, + cpSync, + readFileSync, +} from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { spawnSync } from 'node:child_process'; + +const runner = fileURLToPath(new URL('../run.mjs', import.meta.url)); + +/** Create a real Git fixture so CLI tests exercise trusted base and working-tree changes together. */ +function fixture() { + const cwd = mkdtempSync(join(tmpdir(), '1msg-quality-test-')); + mkdirSync(join(cwd, 'src')); + writeFileSync( + join(cwd, 'package.json'), + '{"name":"quality-fixture","private":true,"type":"module"}\n', + ); + writeFileSync( + join(cwd, 'quality.config.mjs'), + `export default { + schemaVersion:1,profile:'A',defaultBranch:'main',sourceRoots:['src','quality.config.mjs'], + knipConfig:'knip.json',duplicatePaths:['src'],duplicateMaxPercentage:100 + };\n`, + ); + writeFileSync( + join(cwd, 'knip.json'), + JSON.stringify({ entry: ['src/index.js!'], project: ['src/**/*.js!'] }), + ); + const git = (...args) => { + const result = spawnSync('git', args, { cwd, encoding: 'utf8' }); + assert.equal(result.status, 0, result.stderr); + return result.stdout.trim(); + }; + git('init', '-b', 'main'); + git('config', 'user.email', 'quality@example.invalid'); + git('config', 'user.name', 'Quality fixture'); + const commit = () => { + git('add', '.'); + git('commit', '-m', 'test: fixture'); + return git('rev-parse', 'HEAD'); + }; + const run = (...args) => + spawnSync(process.execPath, [runner, ...args], { + cwd, + encoding: 'utf8', + env: { ...process.env, CI: '', QUALITY_BASE: undefined }, + timeout: 60_000, + maxBuffer: 16 * 1024 * 1024, + }); + return { + cwd, + git, + commit, + run, + write: (path, text) => writeFileSync(join(cwd, path), text), + close: () => rmSync(cwd, { recursive: true, force: true }), + }; +} + +test('real CLI blocks undocumented new functions, broad suppression and uncovered files', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + const base = f.commit(); + assert.equal(f.run('guards', '--base', base).status, 0); + f.write( + 'src/index.js', + 'function createWidget() { return 2; }\nconsole.log(createWidget());\n', + ); + assert.match( + f.run('guards', '--base', base).stderr, + /document createWidget/, + ); + f.write( + 'src/index.js', + '/** Construct the default widget. */\nfunction createWidget() { return 2; }\nconsole.log(createWidget());\n', + ); + assert.equal(f.run('guards', '--base', base).status, 0); + f.write('src/index.js', '// @ts-nocheck\nconsole.log("app");\n'); + assert.match(f.run('guards', '--base', base).stderr, /broad lint/); + f.write('rogue.js', 'console.log("forgotten");\n'); + assert.match( + f.run('guards', '--base', base).stderr, + /no declared source root/, + ); + assert.notEqual(f.run('guards', '--base', 'missing-ref').status, 0); + } finally { + f.close(); + } +}); + +test('actual Knip CLI blocks an unused file and unresolved import', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + const base = f.commit(); + assert.equal(f.run('unused-full', '--base', base).status, 0); + f.write('src/forgotten.js', 'export const value = 42;\n'); + const unused = f.run('unused-full', '--base', base); + assert.equal(unused.status, 1, unused.stderr); + assert.match(unused.stderr, /forgotten/); + f.write( + 'src/index.js', + 'import value from "./missing.js"; console.log(value);\n', + ); + assert.match( + f.run('unused-production', '--base', base).stderr, + /unresolved/, + ); + } finally { + f.close(); + } +}); + +test('documentation survives formatting and unrelated callback removal, but new copies still require docs', () => { + const f = fixture(); + try { + f.write( + 'src/index.js', + ` + run(() => { return {name: "removed"}; }); + run(() => { return {name: "retained"}; }); + function load(value) { return request(value, {name: "widget"}); } + `, + ); + const base = f.commit(); + f.write( + 'src/index.js', + ` + run(() => { return {name: 'retained',}; }); + function load(value,) { return request(value, {name: 'widget',},); } + `, + ); + const formatted = f.run('guards', '--base', base); + assert.equal(formatted.status, 0, formatted.stderr); + f.write( + 'src/index.js', + ` + run(() => { return {name: 'retained',}; }); + run(() => { return {name: 'retained',}; }); + function load(value,) { return request(value, {name: 'widget',},); } + `, + ); + const duplicated = f.run('guards', '--base', base); + assert.equal(duplicated.status, 1, duplicated.stderr); + assert.match(duplicated.stderr, /document /); + } finally { + f.close(); + } +}); + +test('actual jscpd CLI blocks a new clone even with unrelated unique lines', () => { + const f = fixture(); + try { + const source = `export function summarize(values) { + const result = []; + for (const value of values) { + const normalized = String(value).trim(); + if (normalized.length > 0) { + result.push({ value: normalized, length: normalized.length }); + } + } + return result.sort((left, right) => left.length - right.length); + }\n`; + f.write('src/index.js', source); + const base = f.commit(); + const clean = f.run('duplicates', '--base', base); + assert.equal(clean.status, 0, clean.stderr); + f.write( + 'src/copy.js', + source + '\nexport const unrelated = "extra unique content";\n', + ); + const duplicated = f.run('duplicates', '--base', base); + assert.equal(duplicated.status, 1, duplicated.stderr); + assert.match(duplicated.stderr, /New or increased/); + } finally { + f.close(); + } +}); + +test('Knip production rejects runtime code referenced only from tests while full accepts it', () => { + const f = fixture(); + try { + f.write( + 'knip.json', + JSON.stringify({ + entry: ['src/index.js!', 'test.js'], + project: ['src/**/*.js!', 'test.js'], + }), + ); + f.write('src/index.js', 'console.log("app");\n'); + f.write('src/helper.js', 'export const value = 42;\n'); + f.write( + 'test.js', + 'import { value } from "./src/helper.js"; console.log(value);\n', + ); + const base = f.commit(); + const full = f.run('unused-full', '--base', base); + assert.equal(full.status, 0, full.stderr); + const production = f.run('unused-production', '--base', base); + assert.equal(production.status, 1, production.stderr); + assert.match(production.stderr, /helper/); + } finally { + f.close(); + } +}); + +test('initial debt is replayed against trusted source, including edited files and newly disconnected imports', () => { + const f = fixture(); + const bootstrap = [ + '--bootstrap', + '--owner', + 'quality', + '--expires', + '2099-01-01', + '--reason', + 'historical fixture debt', + '--issue', + 'TEST-1', + ]; + try { + f.write( + 'src/index.js', + 'import { value } from "./helper.js"; console.log(value);\n', + ); + f.write('src/helper.js', 'export const value = 42;\n'); + f.write('src/forgotten.js', 'export const oldDebt = 1;\n'); + const base = f.commit(); + f.write('src/forgotten.js', 'export const oldDebt = 2;\n'); + f.write('new-tool.mjs', 'console.log(123);'); + f.write( + 'knip.json', + JSON.stringify({ + entry: ['src/index.js!', 'new-tool.mjs'], + project: ['src/**/*.js!', 'new-tool.mjs'], + }), + ); + const historical = f.run('unused-full', '--base', base, ...bootstrap); + assert.equal(historical.status, 0, historical.stderr); + f.write('src/index.js', 'console.log("now disconnected");\n'); + const newDebt = f.run('unused-full', '--base', base, ...bootstrap); + assert.equal(newDebt.status, 1, newDebt.stderr); + assert.match( + newDebt.stderr, + /Cannot baseline a new\/increased finding.*helper/, + ); + } finally { + f.close(); + } +}); + +test('jscpd preserves multiple source roots and enforces its numeric ceiling', () => { + const f = fixture(); + try { + mkdirSync(join(f.cwd, 'runtime')); + const source = `export function summarize(values) { + const result = []; + for (const value of values) { + const normalized = String(value).trim(); + if (normalized.length > 0) result.push({ value: normalized, length: normalized.length }); + } + return result.sort((left, right) => left.length - right.length); + }\n`; + f.write('src/index.js', source); + f.write('runtime/copy.js', source); + f.write( + 'quality.config.mjs', + `export default { schemaVersion:1,profile:'A',sourceRoots:['src','runtime'], + duplicatePaths:['src','runtime'],duplicateMaxPercentage:100 };`, + ); + const base = f.commit(); + const bootstrap = [ + '--bootstrap', + '--owner', + 'quality', + '--expires', + '2099-01-01', + '--reason', + 'historical fixture debt', + '--issue', + 'TEST-1', + ]; + const accepted = f.run('duplicates', '--base', base, ...bootstrap); + assert.equal(accepted.status, 0, accepted.stderr); + f.write( + 'quality.config.mjs', + `export default { schemaVersion:1,profile:'A',sourceRoots:['src','runtime'], + duplicatePaths:['src','runtime'],duplicateMaxPercentage:0 };`, + ); + const percentage = f.run('duplicates', '--base', base); + assert.equal(percentage.status, 1, percentage.stderr); + assert.match(percentage.stderr, /Duplicate percentage/); + } finally { + f.close(); + } +}); + +test('actual dependency-cruiser detects a long runtime cycle and refuses native I/O debt', () => { + const f = fixture(); + const executable = fileURLToPath( + new URL( + '../node_modules/dependency-cruiser/bin/dependency-cruiser.mjs', + import.meta.url, + ), + ); + const command = [ + '--', + process.execPath, + executable, + 'src', + '--config', + 'dependency-cruiser.config.cjs', + '--output-type', + 'json', + ]; + try { + f.write( + 'dependency-cruiser.config.cjs', + `module.exports = { forbidden: [ + {name:'no-runtime-cycles',severity:'error',from:{},to:{circular:true,dependencyTypesNot:['type-only']}}, + {name:'application-no-native-io',severity:'error',from:{path:'src'},to:{dependencyTypes:['core']}}, + ] };`, + ); + f.write('src/index.js', 'import "./second.js"; console.log("one");\n'); + f.write('src/second.js', 'import "./third.js"; console.log("two");\n'); + f.write('src/third.js', 'console.log("three");\n'); + const base = f.commit(); + const clean = f.run( + 'report', + '--kind', + 'depcruiser', + '--base', + base, + ...command, + ); + assert.equal(clean.status, 0, clean.stderr); + f.write('src/third.js', 'import "./index.js"; console.log("three");\n'); + const cycle = f.run( + 'report', + '--kind', + 'depcruiser', + '--base', + base, + ...command, + ); + assert.equal(cycle.status, 1, cycle.stderr); + assert.match(cycle.stderr, /no-runtime-cycles/); + f.write('src/third.js', 'import fs from "node:fs"; console.log(fs);\n'); + const native = f.run( + 'report', + '--kind', + 'depcruiser', + '--base', + base, + '--bootstrap', + '--owner', + 'quality', + '--expires', + '2099-01-01', + '--reason', + 'cannot bless native dependency', + '--issue', + 'TEST-1', + ...command, + ); + assert.equal(native.status, 1, native.stderr); + assert.match(native.stderr, /Non-baselinable architecture/); + } finally { + f.close(); + } +}); + +test('vendored exemption rejects unregistered and modified template files', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + const base = f.commit(); + const template = fileURLToPath(new URL('..', import.meta.url)); + for (const path of [...templateFiles(template), 'template-manifest.json']) { + const destination = join(f.cwd, 'tools/quality', path); + mkdirSync(dirname(destination), { recursive: true }); + cpSync(join(template, path), destination); + } + const clean = f.run('guards', '--base', base); + assert.equal(clean.status, 0, clean.stderr); + f.write('tools/quality/hidden.js', 'export const hidden = 1;'); + assert.match(f.run('guards', '--base', base).stderr, /undeclared/); + rmSync(join(f.cwd, 'tools/quality/hidden.js')); + f.write('tools/quality/README.md', 'unreviewed mutation'); + assert.match(f.run('guards', '--base', base).stderr, /integrity mismatch/); + } finally { + f.close(); + } +}); + +/** Real embedded Svelte clones keep language identity but historical evidence belongs to their physical component. */ +test('jscpd Svelte fragments bootstrap existing clones and reject another participant', () => { + const f = fixture(); + try { + const component = ` +

Summary

\n`; + f.write('src/First.svelte', component); + f.write('src/Second.svelte', component); + const base = f.commit(); + const accepted = f.run( + 'duplicates', + '--base', + base, + '--bootstrap', + '--owner', + 'quality', + '--expires', + '2099-01-01', + '--reason', + 'historical Svelte fixture debt', + '--issue', + 'TEST-1', + ); + assert.equal(accepted.status, 0, accepted.stderr); + const report = JSON.parse( + readFileSync(join(f.cwd, 'quality/reports/duplicates.json'), 'utf8'), + ); + assert.ok( + report.findings.some((finding) => + finding.participants?.some((path) => + path.endsWith('.svelte:javascript'), + ), + ), + ); + assert.ok( + report.findings.every((finding) => + finding.paths.every((path) => path.endsWith('.svelte')), + ), + ); + f.write('src/Third.svelte', component); + const expanded = f.run('duplicates', '--base', base); + assert.equal(expanded.status, 1, expanded.stderr); + assert.match(expanded.stderr, /New or increased/); + } finally { + f.close(); + } +}); + +/** Only the new sealed vendor exemption is omitted from historical graphs; authored stale ignores still fail. */ +test('historical Knip removes a current-only exact vendor ignore without relaxing authored coverage', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + f.write('src/forgotten.js', 'export const historicalDebt = 1;\n'); + const base = f.commit(); + const template = fileURLToPath(new URL('..', import.meta.url)); + for (const path of [...templateFiles(template), 'template-manifest.json']) { + const destination = join(f.cwd, 'tools/quality', path); + mkdirSync(dirname(destination), { recursive: true }); + cpSync(join(template, path), destination); + } + f.write( + 'quality.mjs', + 'import { record } from "./tools/quality/lib/baseline.mjs"; console.log(record("example"));\n', + ); + const config = { + entry: ['src/index.js!', 'quality.mjs'], + project: ['src/**/*.js!', '**/*.mjs'], + ignore: ['tools/quality/**'], + }; + f.write('knip.json', JSON.stringify(config)); + const accepted = f.run( + 'unused-full', + '--base', + base, + '--bootstrap', + '--owner', + 'quality', + '--expires', + '2099-01-01', + '--reason', + 'historical source debt', + '--issue', + 'TEST-1', + ); + assert.equal(accepted.status, 0, accepted.stderr); + config.ignore.push('src/missing/**'); + f.write('knip.json', JSON.stringify(config)); + const invalid = f.run('unused-full', '--base', base); + assert.equal(invalid.status, 1, invalid.stderr); + assert.match(invalid.stderr, /stale exclusion failure.*src\/missing/); + } finally { + f.close(); + } +}); diff --git a/tools/quality/test/ratchet.test.mjs b/tools/quality/test/ratchet.test.mjs new file mode 100644 index 0000000..7722924 --- /dev/null +++ b/tools/quality/test/ratchet.test.mjs @@ -0,0 +1,238 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { assess, parseJson } from '../lib/baseline.mjs'; +import { + knipRecords, + duplicateRecords, + eslintRecords, + tokenFingerprint, +} from '../lib/reports.mjs'; +import { functionsIn, suppressionErrors } from '../lib/guards.mjs'; + +const owner = { + owner: 'quality-maintainers', + reason: 'Existing complexity', + issue: '1MSG-156', + expires: '2026-11-12', +}; +const baseline = (entries) => ({ schemaVersion: 1, entries }); +const allowance = (key, value) => ({ key, value, ...owner }); + +test('growth cannot be offset by reductions, and reductions retire allowances', () => { + const old = baseline([allowance('a', 25), allowance('b', 20)]); + assert.match( + assess( + [ + { key: 'a', value: 26 }, + { key: 'b', value: 15 }, + ], + old, + old, + '2026-10-12', + ).join('\n'), + /increased/, + ); + assert.match( + assess( + [ + { key: 'a', value: 25 }, + { key: 'b', value: 15 }, + ], + old, + old, + '2026-10-12', + ).join('\n'), + /Reduce/, + ); +}); + +test('new or increased baselines, expiry extensions and stale allowances fail', () => { + const old = baseline([allowance('a', 25)]); + const next = baseline([ + { ...allowance('a', 26), expires: '2026-12-12' }, + allowance('new', 1), + ]); + const errors = assess( + [{ key: 'a', value: 26 }], + next, + old, + '2026-10-12', + ).join('\n'); + assert.match(errors, /expanded/); + assert.match(errors, /expiry extended/); + assert.match(errors, /stale/); + assert.match(assess([], old, old, '2026-12-01').join('\n'), /Expired/); +}); + +test('empty or malformed analyzer reports are not successful checks', () => { + assert.throws(() => parseJson('Killed', 'Knip'), /complete JSON/); + assert.throws(() => knipRecords({}), /schema/); + assert.throws( + () => + duplicateRecords({ + duplicates: [], + statistics: { total: { sources: 0 } }, + }), + /empty/, + ); + assert.throws(() => eslintRecords([]), /empty/); +}); + +test('Knip distinguishes unresolved imports, unused dependencies and exported symbols', () => { + const rows = knipRecords({ + issues: [ + { + file: 'src/a.ts', + exports: [{ name: 'thing', line: 3 }], + unresolved: [{ name: './missing', line: 1 }], + files: [], + }, + { file: 'package.json', dependencies: [{ name: 'unused' }] }, + ], + }); + assert.equal(rows.length, 3); + assert.ok(rows.some((row) => row.rule === 'unresolved')); + const moved = knipRecords({ + issues: [{ file: 'src/a.ts', exports: [{ name: 'thing', line: 99 }] }], + }); + assert.equal(rows.find((row) => row.rule === 'exports').key, moved[0].key); +}); + +test('duplicate identity ignores line moves but notices additional participants and extended code', () => { + const clone = { + format: 'typescript', + fragment: 'const value = input + 3;', + tokens: 7, + firstFile: { name: 'src/a.ts', start: 1, end: 2 }, + secondFile: { name: 'src/b.ts', start: 7, end: 8 }, + }; + const report = (clones) => ({ + duplicates: clones, + statistics: { total: { sources: 3 } }, + }); + const original = duplicateRecords(report([clone])); + const moved = duplicateRecords( + report([ + { ...clone, firstFile: { ...clone.firstFile, start: 9, end: 10 } }, + ]), + ); + assert.equal(original[0].key, moved[0].key); + assert.notEqual( + original[0].key, + duplicateRecords( + report([clone, { ...clone, secondFile: { name: 'src/c.ts' } }]), + )[0].key, + ); + assert.notEqual( + original[0].key, + duplicateRecords( + report([{ ...clone, fragment: clone.fragment + 'return value;' }]), + )[0].key, + ); + assert.equal( + tokenFingerprint('const a = 1;'), + tokenFingerprint('/* moved */ const a=1;'), + ); + assert.notEqual( + tokenFingerprint('const a="a b";'), + tokenFingerprint('const a="ab";'), + ); +}); + +test('documentation covers private methods, arrow helpers and Svelte scripts', () => { + const source = + '/** Resolve the current owner. */\nconst owner = () => 1;\nclass Foo {\n/** Release the acquired resource. */\nprivate release() {}\n}'; + const functions = functionsIn('src/a.ts', source); + assert.equal(functions.length, 2); + assert.ok(functions.every((fn) => fn.comments.length)); + assert.equal( + functionsIn( + 'View.svelte', + '

Hi

', + ).length, + 1, + ); + assert.throws( + () => functionsIn('broken.ts', 'function f( {'), + /Cannot parse/, + ); +}); + +test('documentation fingerprint preserves array holes and changes to callback ownership', () => { + const signature = (source) => functionsIn('src/a.ts', source)[0].signature; + assert.equal( + signature('function f() { return [1]; }'), + signature('function f() { return [1,]; }'), + ); + assert.notEqual( + signature('function f() { return []; }'), + signature('function f() { return [,]; }'), + ); + assert.notEqual( + signature('function f() { return [1]; }'), + signature('function f() { return [1,,]; }'), + ); + assert.notEqual( + functionsIn('src/a.ts', 'first(() => { return 1; });')[0].key, + functionsIn('src/a.ts', 'second(() => { return 1; });')[0].key, + ); +}); + +test('whole-file line limits keep their identity when the diagnostic moves between functions', () => { + const finding = (line) => + eslintRecords([ + { + filePath: 'lib/guards.mjs', + messages: [ + { + ruleId: 'max-lines', + message: 'File has too many lines (600). Maximum allowed is 500.', + line, + column: 1, + }, + ], + }, + ])[0]; + assert.equal(finding(20).key, 'lib/guards.mjs|max-lines||0'); + assert.equal(finding(120).key, finding(20).key); +}); + +test('suppression gates do not mistake strings for directives', () => { + assert.equal( + suppressionErrors('a.ts', 'const example = "// @ts-ignore";', {}).length, + 0, + ); + assert.equal( + suppressionErrors('a.ts', '// @ts-nocheck\nexport const a = 1;', {}).length, + 1, + ); + assert.equal( + suppressionErrors('a.ts', '/* eslint-disable */\nexport const a = 1;', {}) + .length, + 1, + ); + assert.equal( + suppressionErrors( + 'a.ts', + '// eslint-disable-next-line no-alert -- Temporary browser compatibility\nalert(1);', + {}, + ).length, + 0, + ); + assert.equal( + suppressionErrors( + 'a.ts', + '// @ts-expect-error: Verify rejected primitive input\nf(1);', + {}, + ).length, + 1, + ); + assert.equal( + suppressionErrors( + 'negative.test.ts', + '// @ts-expect-error: Verify rejected primitive input\nf(1);', + { negativeTypeTests: ['*.test.ts'] }, + ).length, + 0, + ); +}); diff --git a/tools/quality/tsconfig.next.json b/tools/quality/tsconfig.next.json new file mode 100644 index 0000000..583277d --- /dev/null +++ b/tools/quality/tsconfig.next.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "preserve", + "noEmit": true, + "isolatedModules": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "noEmitOnError": true, + "plugins": [{ "name": "next" }] + } +} diff --git a/tools/quality/tsconfig.node.json b/tools/quality/tsconfig.node.json new file mode 100644 index 0000000..cba7925 --- /dev/null +++ b/tools/quality/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "noEmitOnError": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/tools/quality/tsconfig.svelte.json b/tools/quality/tsconfig.svelte.json new file mode 100644 index 0000000..da3596a --- /dev/null +++ b/tools/quality/tsconfig.svelte.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "isolatedModules": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "noEmitOnError": true + } +} From 9cda3900b3ebbd7d9d575b567b24c8473a47fbd0 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Mon, 12 Oct 2026 20:23:27 +0500 Subject: [PATCH 2/8] fix: verify incoming SDK bytes before adopting generation manifests --- quality/generator/generate.mjs | 12 ++++++++---- quality/generator/verify-negative.mjs | 24 +++++++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/quality/generator/generate.mjs b/quality/generator/generate.mjs index d26a6a9..00da04d 100644 --- a/quality/generator/generate.mjs +++ b/quality/generator/generate.mjs @@ -128,14 +128,18 @@ try { } await writeFile(inventoryPath, JSON.stringify(expected, null, 2) + "\n"); } else { - for (const actual of [ - await inventory(root), - JSON.parse(await readFile(inventoryPath, "utf8")), - ]) + // Synchronization may advance only the manifest after independently verifying + // the incoming producer output; it must never overwrite differing bytes. + const candidates = [await inventory(root)]; + if (!process.argv.includes("--adopt")) + candidates.push(JSON.parse(await readFile(inventoryPath, "utf8"))); + for (const actual of candidates) if (JSON.stringify(actual) !== JSON.stringify(expected)) throw new Error( "Generated drift: review producer then run node quality/generator/generate.mjs --write", ); + if (process.argv.includes("--adopt")) + await writeFile(inventoryPath, JSON.stringify(expected, null, 2) + "\n"); } console.log( `Verified ${Object.keys(expected).length} generated ${config.language} code paths`, diff --git a/quality/generator/verify-negative.mjs b/quality/generator/verify-negative.mjs index 993a151..8d05c1b 100644 --- a/quality/generator/verify-negative.mjs +++ b/quality/generator/verify-negative.mjs @@ -19,17 +19,19 @@ const ignorePath = join(root, ".gitignore"); const originalIgnore = readFileSync(ignorePath); /** Require the real generation replay to fail specifically on output drift, not a missing tool or configuration. */ function rejectDrift() { - const result = spawnSync( - process.execPath, - ["quality/generator/generate.mjs"], - { cwd: root, encoding: "utf8", timeout: 120000 }, - ); - assert.notEqual(result.status, 0, "generation accepted modified output"); - assert.match( - result.stderr + result.stdout, - /Generated drift/, - "fixture failed for an unrelated reason", - ); + for (const flags of [[], ["--adopt"]]) { + const result = spawnSync( + process.execPath, + ["quality/generator/generate.mjs", ...flags], + { cwd: root, encoding: "utf8", timeout: 120000 }, + ); + assert.notEqual(result.status, 0, "generation accepted modified output"); + assert.match( + result.stderr + result.stdout, + /Generated drift/, + "fixture failed for an unrelated reason", + ); + } } try { writeFileSync( From d6a9fb63f4c39b890c36c54ab8b6c01e30c34985 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 00:24:18 +0500 Subject: [PATCH 3/8] ci(quality): update sealed analyzer identity checks to 1.0.8 --- tools/quality/README.md | 27 ++- tools/quality/canonical-duplicates.mjs | 128 +++++++++++++ tools/quality/complexity.mjs | 83 +++++++++ tools/quality/lib/guards.mjs | 74 +++++--- tools/quality/lib/historical.mjs | 2 +- tools/quality/lib/reports.mjs | 222 ++++++++++++++++++++-- tools/quality/package-lock.json | 4 +- tools/quality/package.json | 2 +- tools/quality/run.mjs | 8 + tools/quality/template-manifest.json | 24 ++- tools/quality/test/cli.test.mjs | 241 ++++++++++++++++++++++++ tools/quality/test/complexity.test.mjs | 247 +++++++++++++++++++++++++ tools/quality/test/ratchet.test.mjs | 28 ++- tools/quality/test/reports.test.mjs | 192 +++++++++++++++++++ 14 files changed, 1226 insertions(+), 56 deletions(-) create mode 100644 tools/quality/canonical-duplicates.mjs create mode 100644 tools/quality/complexity.mjs create mode 100644 tools/quality/test/complexity.test.mjs create mode 100644 tools/quality/test/reports.test.mjs diff --git a/tools/quality/README.md b/tools/quality/README.md index ebb38d7..4b600bd 100644 --- a/tools/quality/README.md +++ b/tools/quality/README.md @@ -1,4 +1,4 @@ -# 1MSG quality template 1.0.2 +# 1MSG quality template 1.0.8 Vendored, private template for 1MSG-156. Install its exact tools with `npm --prefix tools/quality ci` on Node 24.19.0. The lockfile and @@ -83,3 +83,28 @@ Integrity verification prevents hiding authored code under the vendor exemption. No analyzer flag may depend on CI or a skip-type-aware environment variable. Version 1.0.2 resolves Svelte embedded clone paths to their physical source while retaining fragment identity. Initial Knip replay omits only the exact current-only sealed vendor ignore; authored stale ignores remain errors. + +## Canonical maintainability measurement (1.0.3) + +For adoption that includes formatting, run `node tools/quality/complexity.mjs --config eslint.complexity.config.mjs` as the analyzer inside the existing `report --kind eslint --name complexity` gate. Both trusted historical source and current source are independently formatted in memory with the pinned Prettier version and sealed policy before the same ESLint rules execute. Files on disk are never rewritten. This gives line metrics the same unit of measurement; AST complexity and the per-finding ratchet remain enforced. The original Git source hash remains adoption evidence. The JSON report includes canonical source so diagnostic locations identify the correct function after formatting. Formatter/parse failures are fatal. This does not replace `Prettier --check` on the actual checkout. + +Existing consumers pinned to 1.0.2 do not need a policy change; 1.0.3 adds the explicit canonical measurement command. + +For JS/TS formatting migrations, `duplicateCanonicalFormat: true` measures both trusted base and current source after the same pinned formatter in disposable copies. Declare the supported `duplicateFormats` (`javascript`, `typescript`, `jsx`, `tsx`) and exact ignored dependency/generated paths. Source files stay unchanged. New/grown clone groups still fail even if the aggregate percentage falls. Unsupported framework source, unexpected symlinks, empty coverage or failed formatting are analyzer failures. Report line numbers refer to canonical source fragments. + +Version 1.0.6 runs canonical complexity with inline ESLint configuration disabled on both sides. Legacy directives for unrelated framework plugins cannot corrupt metric coverage, and a source comment cannot suppress complexity debt. The separate source suppression guard still enforces the current-code policy. Trusted replay also copies exact Jest config filenames as analyzer inputs, allowing Knip to load current test-runner configuration against historical application and test source. Ordinary source files continue to come exclusively from the trusted Git archive. + +Version 1.0.7 parses JS/TS/JSX/TSX with the pinned TypeScript compiler and prints an in-memory, comment-free metric input before pinned Prettier formatting. Comments inside JSX callbacks otherwise change indentation and wrap executable lines, inflating line debt despite `skipComments`. Both current and trusted historical sources use the same normalization; recompute both sides when adopting this version. No rule limits or baseline allowances change. The original files are not rewritten, and strings, regular expressions, template literals and rendered JSX content remain data rather than comment matches. Unsupported source extensions and syntax errors fail closed before recovered syntax can become a metric report. + +The 31-test suite includes actual CLI fixtures proving that JSX documentation leaves file/function line metrics unchanged, an added statement still increases those metrics, malformed JS/TSX fails, and canonical string/tagged-template/regular-expression, JSX rendering and automatic-semicolon behavior is preserved. JSX assertions compare rendered text and element order because formatting may split adjacent text nodes. Formatting and documentation guards still inspect the actual checkout. Consumers remaining on sealed 1.0.2 are unchanged by this release. + +## Version 1.0.8 + +Complexity findings use complete lexical ownership (class, function, binding, +property and call argument), independent of emitted diagnostic order. Fixing an +older callback therefore cannot renumber a different callback's allowance. +Ambiguous sibling scopes are tied to ordered, comment-free AST evidence; changed +or indistinguishable groups fail closed. The real CLI fixtures verify both +legitimate debt reduction and rejection of transferred/increased allowances. +Existing consumers must replay historical source with this version when adopting +the new key schema; old diagnostic ordinals are never silently migrated. diff --git a/tools/quality/canonical-duplicates.mjs b/tools/quality/canonical-duplicates.mjs new file mode 100644 index 0000000..c706926 --- /dev/null +++ b/tools/quality/canonical-duplicates.mjs @@ -0,0 +1,128 @@ +import { spawnSync } from 'node:child_process'; +import { + lstat, + mkdir, + mkdtemp, + readFile, + readdir, + rm, + writeFile, + realpath, +} from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { dirname, join, resolve } from 'node:path'; +import { format } from 'prettier'; +import picomatch from 'picomatch'; +import policy from './prettier.config.mjs'; +const config = JSON.parse(process.argv[2]); +const root = process.cwd(); +if (!Array.isArray(config.duplicatePaths) || !config.duplicatePaths.length) + throw new Error('Canonical clone roots are required'); +for (const file of config.duplicatePaths) + if ( + typeof file !== 'string' || + file.startsWith('/') || + file.split(/[\\/]/).includes('..') + ) + throw new Error('Clone root must remain inside the repository'); +const formats = config.duplicateFormats ?? [ + 'javascript', + 'typescript', + 'jsx', + 'tsx', +]; +if ( + !formats.length || + formats.some( + (value) => !['javascript', 'typescript', 'jsx', 'tsx'].includes(value), + ) +) + throw new Error( + 'Canonical clone measurement supports only declared JavaScript and TypeScript formats', + ); +const temporary = await realpath( + await mkdtemp(join(tmpdir(), 'canonical-clones-')), +); +const ignored = picomatch(config.duplicateIgnore ?? [], { dot: true }); +let files = 0; +/** Inventory declared roots without following symlinks and format each authored source with the same sealed policy. */ +async function copy(file) { + if (ignored(file)) return; + const info = await lstat(join(root, file)); + if (info.isSymbolicLink()) throw Error(`Unreviewed source symlink: ${file}`); + if (info.isDirectory()) { + for (const entry of await readdir(join(root, file))) + await copy(join(file, entry)); + return; + } + if (/\.(svelte|vue)$/.test(file)) + throw new Error( + `Canonical clone measurement needs a framework formatter for ${file}`, + ); + if (!/\.[cm]?[jt]sx?$/.test(file)) return; + const canonical = await format(await readFile(join(root, file), 'utf8'), { + ...policy, + filepath: file, + }); + const target = join(temporary, file); + await mkdir(dirname(target), { recursive: true }); + await writeFile(target, canonical); + files++; +} +/** Restore portable source identities after analyzing the temporary canonical copy; fragments retain their measured text. */ +function originalPaths(value) { + if (typeof value === 'string' && value.startsWith(temporary + '/')) + return join(root, value.slice(temporary.length + 1)); + if (Array.isArray(value)) return value.map(originalPaths); + if (value && typeof value === 'object') + return Object.fromEntries( + Object.entries(value).map(([key, item]) => [ + originalPaths(key), + originalPaths(item), + ]), + ); + return value; +} +try { + for (const file of config.duplicatePaths) await copy(file); + if (!files) throw Error('Canonical clone inventory is empty'); + const tool = new URL('./node_modules/jscpd/run-jscpd.js', import.meta.url) + .pathname; + const result = spawnSync( + process.execPath, + [ + tool, + ...config.duplicatePaths, + '--reporters', + 'json', + '--output', + 'reports', + '--mode', + 'mild', + '--min-lines', + '5', + '--min-tokens', + '50', + '--silent', + '--absolute', + '--format', + formats.join(','), + ], + { + cwd: temporary, + encoding: 'utf8', + timeout: 180000, + maxBuffer: 50 * 1024 * 1024, + }, + ); + if (result.status !== 0 || result.error || result.signal) + throw Error(result.stderr || result.stdout || String(result.error)); + const report = JSON.parse( + await readFile(join(temporary, 'reports/jscpd-report.json'), 'utf8'), + ); + if (report.duplicates.some((clone) => typeof clone.fragment !== 'string')) + throw Error('Missing canonical clone fragment'); + process.stdout.write(JSON.stringify(originalPaths(report))); +} finally { + await rm(temporary, { recursive: true, force: true }); +} diff --git a/tools/quality/complexity.mjs b/tools/quality/complexity.mjs new file mode 100644 index 0000000..fb0b27a --- /dev/null +++ b/tools/quality/complexity.mjs @@ -0,0 +1,83 @@ +#!/usr/bin/env node +import { realpathSync } from 'node:fs'; +import { readFile } from 'node:fs/promises'; +import { extname } from 'node:path'; +import { pathToFileURL } from 'node:url'; + +import { ESLint } from 'eslint'; +import { format } from 'prettier'; +import ts from 'typescript'; + +import policy from './prettier.config.mjs'; + +/** Remove only parsed comments before formatting so documentation cannot inflate wrapped code lines; reject unsupported or invalid syntax. */ +function metricSource(source, filePath) { + if (!/^[.](?:[cm]?[jt]s|[jt]sx)$/.test(extname(filePath))) + throw new Error(`Unsupported complexity source: ${filePath}`); + const syntax = ts.createSourceFile( + filePath, + source, + ts.ScriptTarget.Latest, + true, + ); + if (syntax.parseDiagnostics.length) { + const diagnostic = syntax.parseDiagnostics[0]; + throw new Error( + `Complexity parse failed: ${filePath}: ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`, + ); + } + return ts + .createPrinter({ removeComments: true, newLine: ts.NewLineKind.LineFeed }) + .printFile(syntax); +} + +/** Measure comment-free source with the same pinned formatting policy, retaining canonical text for diagnostic scope identities. */ +export async function measureComplexity(config, targets) { + const eslint = new ESLint({ + overrideConfigFile: config, + allowInlineConfig: false, + }); + const inventory = await eslint.lintFiles(targets); + if (!inventory.length) + throw new Error('Complexity source inventory is empty'); + const reports = []; + for (const file of inventory) { + if (file.fatalErrorCount) + throw new Error(`Complexity parse failed: ${file.filePath}`); + const source = await readFile(file.filePath, 'utf8'); + const canonical = await format(metricSource(source, file.filePath), { + ...policy, + filepath: file.filePath, + }); + const [report] = await eslint.lintText(canonical, { + filePath: file.filePath, + }); + if (!report || report.fatalErrorCount) + throw new Error(`Complexity parse failed: ${file.filePath}`); + reports.push({ ...report, source: canonical }); + } + return reports; +} + +/** Keep formatter, parser and inventory failures distinct from ordinary maintainability diagnostics. */ +async function main() { + const args = process.argv.slice(2); + const position = args.indexOf('--config'); + if (position < 0 || !args[position + 1]) + throw new Error('Complexity measurement requires --config'); + const [config] = args.splice(position, 2).slice(1); + const reports = await measureComplexity(config, args.length ? args : ['.']); + process.stdout.write(JSON.stringify(reports)); + if (reports.some((report) => report.errorCount || report.warningCount)) + process.exitCode = 1; +} + +if ( + process.argv[1] && + import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href +) { + main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 2; + }); +} diff --git a/tools/quality/lib/guards.mjs b/tools/quality/lib/guards.mjs index 500c8fe..f27c583 100644 --- a/tools/quality/lib/guards.mjs +++ b/tools/quality/lib/guards.mjs @@ -30,6 +30,11 @@ export function validateConfig( 'sourceRoots must inventory the authored source and tooling', ); } + if ( + config.duplicateCanonicalFormat !== undefined && + typeof config.duplicateCanonicalFormat !== 'boolean' + ) + throw new Error('duplicateCanonicalFormat must be an explicit boolean'); for (const root of config.sourceRoots) { if (!existsSync(root)) throw new Error(`Missing source root: ${root}`); } @@ -93,28 +98,32 @@ export function parseUnits(path, text) { ]; } -/** Compare semantic tokens so formatting/quote changes do not create a false method edit. */ -function functionFingerprint(fragment) { - const scanner = ts.createScanner( - ts.ScriptTarget.Latest, - true, - ts.LanguageVariant.JSX, - fragment, - ); +/** Compare parsed semantic tokens, including template segments, without treating comments or optional trailing commas as method edits. */ +function functionFingerprint(node, ast) { const tokens = []; - for ( - let token = scanner.scan(); - token !== ts.SyntaxKind.EndOfFileToken; - token = scanner.scan() - ) { - const value = [ - ts.SyntaxKind.StringLiteral, - ts.SyntaxKind.NoSubstitutionTemplateLiteral, - ].includes(token) - ? scanner.getTokenValue() - : scanner.getTokenText(); - tokens.push([token, value]); + /** Traverse lexical tokens rather than rescanning text, so template-expression context remains accurate. */ + function visit(current) { + if ( + current.kind >= ts.SyntaxKind.FirstJSDocNode && + current.kind <= ts.SyntaxKind.LastJSDocNode + ) + return; + const children = current.getChildren(ast); + if (children.length) { + for (const child of children) visit(child); + return; + } + if (current.kind === ts.SyntaxKind.SyntaxList) return; + const value = + ts.isStringLiteralLike(current) || + ts.isTemplateHead(current) || + ts.isTemplateMiddle(current) || + ts.isTemplateTail(current) + ? current.text + : current.getText(ast); + tokens.push([current.kind, value]); } + visit(node); const meaningful = tokens.filter(([kind], index) => { if (kind !== ts.SyntaxKind.CommaToken) return true; const next = tokens[index + 1]?.[0]; @@ -134,6 +143,27 @@ function functionFingerprint(fragment) { return digest(JSON.stringify(meaningful)); } +/** Identify a call chain without embedding mutable arguments or comments into callback ownership. */ +function lexicalCall(node, ast) { + if ( + ts.isParenthesizedExpression(node) || + ts.isAsExpression(node) || + ts.isNonNullExpression(node) + ) + return lexicalCall(node.expression, ast); + if (ts.isCallExpression(node) || ts.isNewExpression(node)) + return `${lexicalCall(node.expression, ast)}()`; + if (ts.isPropertyAccessExpression(node)) + return `${lexicalCall(node.expression, ast)}.${node.name.text}`; + if (ts.isElementAccessExpression(node)) { + const key = ts.isStringLiteralLike(node.argumentExpression) + ? node.argumentExpression.text + : ''; + return `${lexicalCall(node.expression, ast)}[${key}]`; + } + return ts.isIdentifier(node) ? node.text : ''; +} + /** Identify callbacks by their lexical owner, not their position among unrelated functions. */ function lexicalScope(node, ast) { const owners = []; @@ -142,7 +172,7 @@ function lexicalScope(node, ast) { const name = current.name ?? current.parent?.name; if (name) owners.push(name.getText(ast)); } else if (ts.isCallExpression(current)) { - owners.push(current.expression.getText(ast)); + owners.push(lexicalCall(current.expression, ast)); } } return owners.reverse().join('/'); @@ -212,7 +242,7 @@ export function functionsIn(path, text) { : []; functions.push({ key: `${suffix}:${lexicalScope(node, ast)}:${name}`, - signature: functionFingerprint(node.getText(ast)), + signature: functionFingerprint(node, ast), name, comments: [ ...comments, diff --git a/tools/quality/lib/historical.mjs b/tools/quality/lib/historical.mjs index 7ed6be8..29ba0a2 100644 --- a/tools/quality/lib/historical.mjs +++ b/tools/quality/lib/historical.mjs @@ -94,7 +94,7 @@ export function historicalAnalysis(base, config, templateDirectory, analyze) { cpSync('package.json', join(snapshot, 'package.json')); } const configuration = paths.filter((path) => - /(?:^|\/)(?:eslint(?:\.[\w-]+)?\.config\.[cm]?js|dependency-cruiser(?:\.[\w-]+)?\.config\.[cm]?js|tsconfig(?:\.[\w-]+)?\.json|quality\.config\.mjs)$/.test( + /(?:^|\/)(?:eslint(?:\.[\w-]+)?\.config\.[cm]?js|dependency-cruiser(?:\.[\w-]+)?\.config\.[cm]?js|jest(?:\.[\w-]+)?\.config\.[cm]?[jt]s|tsconfig(?:\.[\w-]+)?\.json|quality\.config\.mjs)$/.test( path, ), ); diff --git a/tools/quality/lib/reports.mjs b/tools/quality/lib/reports.mjs index 19c9a8e..b04abef 100644 --- a/tools/quality/lib/reports.mjs +++ b/tools/quality/lib/reports.mjs @@ -184,25 +184,200 @@ export function duplicateRecords(report) { .sort((a, b) => a.key.localeCompare(b.key)); } -/** Locate the enclosing declaration for an ESLint diagnostic without using unstable line numbers as identity. */ -function scopeAt(source, line, column) { +/** Fingerprint parsed syntax without comments, retaining literal and template text that can change callback behavior. */ +function syntaxFingerprint(node, source) { + const tokens = []; + /** Preserve parser token boundaries, including template substitutions, instead of rescanning a context-free fragment. */ + function visit(current) { + if ( + current.kind >= ts.SyntaxKind.FirstJSDocNode && + current.kind <= ts.SyntaxKind.LastJSDocNode + ) + return; + const children = current.getChildren(source); + if (children.length) { + for (const child of children) visit(child); + } else if (current.kind !== ts.SyntaxKind.SyntaxList) { + tokens.push([current.kind, current.getText(source)]); + } + } + visit(node); + return digest(JSON.stringify(tokens)); +} + +/** Identify a callable expression without incorporating the bodies or mutable arguments of other callbacks in its chain. */ +function callTarget(node, source) { + if ( + ts.isParenthesizedExpression(node) || + ts.isAsExpression(node) || + ts.isTypeAssertionExpression(node) || + ts.isNonNullExpression(node) || + ts.isSatisfiesExpression(node) + ) + return callTarget(node.expression, source); + if (ts.isIdentifier(node)) return ['identifier', node.text]; + if (node.kind === ts.SyntaxKind.ThisKeyword) return ['this']; + if (node.kind === ts.SyntaxKind.SuperKeyword) return ['super']; + if (ts.isPropertyAccessExpression(node)) + return ['member', callTarget(node.expression, source), node.name.text]; + if (ts.isElementAccessExpression(node)) + return [ + 'element', + callTarget(node.expression, source), + syntaxFingerprint(node.argumentExpression, source), + ]; + if (ts.isCallExpression(node) || ts.isNewExpression(node)) + return [ts.SyntaxKind[node.kind], callTarget(node.expression, source)]; + if (ts.isFunctionLike(node)) + return [ + ts.SyntaxKind[node.kind], + node.name?.getText(source) ?? '', + ]; + return ['expression', syntaxFingerprint(node, source)]; +} + +/** Keep ordinary binding names readable while preserving computed and destructured names without formatting-sensitive text. */ +function ownerName(node, source) { + if (ts.isIdentifier(node) || ts.isPrivateIdentifier(node)) return node.text; + if (ts.isStringLiteralLike(node) || ts.isNumericLiteral(node)) + return ['literal', node.text]; + return ['computed', syntaxFingerprint(node, source)]; +} + +/** Include every named lexical owner and each enclosing call's argument position, without using source lines or diagnostic order. */ +function lexicalOwners(node, source) { + const owners = []; + let child; + for ( + let current = node; + current && !ts.isSourceFile(current); + current = current.parent + ) { + if (ts.isCallExpression(current) || ts.isNewExpression(current)) { + const argument = current.arguments?.indexOf(child) ?? -1; + owners.push([ + ts.SyntaxKind[current.kind], + callTarget(current.expression, source), + argument < 0 ? 'callee' : argument, + ]); + } else if ( + ts.isBinaryExpression(current) && + current.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && + current.operatorToken.kind <= ts.SyntaxKind.LastAssignment + ) { + owners.push(['assignment', callTarget(current.left, source)]); + } else if (ts.isFunctionLike(current) || ts.isClassLike(current)) { + owners.push([ + ts.SyntaxKind[current.kind], + current.name ? ownerName(current.name, source) : '', + current.modifiers?.some( + (modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword, + ) + ? 'static' + : 'instance', + ]); + } else if (current.name) { + owners.push([ + ts.SyntaxKind[current.kind], + ownerName(current.name, source), + ]); + } else if ( + ts.isJsxOpeningElement(current) || + ts.isJsxSelfClosingElement(current) + ) { + owners.push(['jsx', current.tagName.getText(source)]); + } + child = current; + } + return owners.reverse(); +} + +/** Recognize independently reported nesting nodes; sibling blocks must not share a function's depth allowance. */ +function isDepthScope(node) { + return [ + ts.SyntaxKind.IfStatement, + ts.SyntaxKind.ForStatement, + ts.SyntaxKind.ForInStatement, + ts.SyntaxKind.ForOfStatement, + ts.SyntaxKind.WhileStatement, + ts.SyntaxKind.DoStatement, + ts.SyntaxKind.SwitchStatement, + ts.SyntaxKind.TryStatement, + ts.SyntaxKind.WithStatement, + ].includes(node.kind); +} + +/** Index all lexical scopes, including functions below lint thresholds, so disappearing diagnostics cannot renumber another allowance. */ +function scopeIdentities(source, depth = false) { + const groups = new Map(); + /** Inventory complete syntax before resolving any diagnostic, keeping below-threshold siblings in ambiguity decisions. */ + function visit(node) { + const included = depth + ? isDepthScope(node) + : (ts.isFunctionLike(node) && node.body) || + ts.isClassStaticBlockDeclaration(node) || + (ts.isPropertyDeclaration(node) && node.initializer); + if (included) { + const owners = lexicalOwners(node, source); + if (depth) owners.push(['nesting', ts.SyntaxKind[node.kind]]); + if (ts.isClassStaticBlockDeclaration(node)) owners.push(['static-block']); + const owner = JSON.stringify(owners); + const group = groups.get(owner) ?? []; + group.push(node); + groups.set(owner, group); + } + ts.forEachChild(node, visit); + } + visit(source); + const identities = new Map(); + for (const [owner, nodes] of groups) { + if (nodes.length === 1) { + identities.set(nodes[0], owner); + continue; + } + const fingerprints = nodes.map((node) => syntaxFingerprint(node, source)); + // Preserve source order in ambiguous groups: swapping a large and small body must not transfer the large allowance. + const group = digest(JSON.stringify(fingerprints)); + for (const [index, node] of nodes.entries()) { + const fingerprint = fingerprints[index]; + // A changed ambiguous group loses every old allowance; even matching another old body cannot borrow its budget. + identities.set( + node, + fingerprints.indexOf(fingerprint) === + fingerprints.lastIndexOf(fingerprint) + ? `${owner}|group:${group}|member:${fingerprint}` + : null, + ); + } + } + return identities; +} + +/** Resolve a diagnostic to its innermost inventoried owner; indistinguishable siblings and missing locations fail closed. */ +function scopeAt(source, identities, line, column) { const offset = source.getPositionOfLineAndCharacter( Math.max(0, line - 1), Math.max(0, column - 1), ); - let scope = ''; - const visit = (node) => { - if (node.pos <= offset && node.end >= offset) { - if (ts.isFunctionLike(node)) - scope = - node.name?.getText(source) ?? - node.parent.name?.getText(source) ?? - ''; + let matched; + /** Select the innermost scope containing the reported token, never an unrelated neighboring declaration. */ + function visit(node) { + if (node.getStart(source) <= offset && node.end > offset) { + if (identities.has(node)) matched = node; ts.forEachChild(node, visit); } - }; + } visit(source); - return scope; + if (!matched) + throw new Error( + `No lexical scope for ESLint diagnostic: ${source.fileName}:${line}:${column}`, + ); + const identity = identities.get(matched); + if (identity === null) + throw new Error( + `Ambiguous lexical scope for ESLint diagnostic: ${source.fileName}:${line}:${column}`, + ); + return identity; } /** Only complexity diagnostics may use a debt baseline; parser, typed and correctness errors remain fatal. */ @@ -221,13 +396,18 @@ export function eslintRecords(report) { for (const file of report) { const path = repoPath(file.filePath); if (!Array.isArray(file.messages)) throw new Error('Invalid ESLint report'); + if (file.messages.length === 0) continue; const source = ts.createSourceFile( path, - currentFile(path) ?? '', + file.source ?? currentFile(path) ?? '', ts.ScriptTarget.Latest, true, ); - const occurrences = new Map(); + if (source.parseDiagnostics.length) + throw new Error(`Invalid syntax in ESLint scope evidence: ${path}`); + const functions = scopeIdentities(source); + const depths = scopeIdentities(source, true); + const identities = new Set(); for (const message of file.messages) { if (message.fatal || !allowed.has(message.ruleId)) { throw new Error( @@ -248,12 +428,18 @@ export function eslintRecords(report) { const scope = message.ruleId === 'max-lines' ? '' - : scopeAt(source, message.line ?? 1, message.column ?? 1); + : scopeAt( + source, + message.ruleId === 'max-depth' ? depths : functions, + message.line ?? 1, + message.column ?? 1, + ); const identity = `${path}|${message.ruleId}|${scope}`; - const occurrence = occurrences.get(identity) ?? 0; - occurrences.set(identity, occurrence + 1); + if (identities.has(identity)) + throw new Error(`Duplicate ESLint diagnostic identity: ${identity}`); + identities.add(identity); results.push( - record(`${identity}|${occurrence}`, Number(values[1]), { + record(identity, Number(values[1]), { path, rule: message.ruleId, scope, diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json index 5b96b4b..8ad5519 100644 --- a/tools/quality/package-lock.json +++ b/tools/quality/package-lock.json @@ -1,12 +1,12 @@ { "name": "@1msg/quality-template", - "version": "1.0.2", + "version": "1.0.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@1msg/quality-template", - "version": "1.0.2", + "version": "1.0.8", "dependencies": { "@eslint/js": "9.39.5", "dependency-cruiser": "18.6.0", diff --git a/tools/quality/package.json b/tools/quality/package.json index 62d20c2..b71d5b0 100644 --- a/tools/quality/package.json +++ b/tools/quality/package.json @@ -1,6 +1,6 @@ { "name": "@1msg/quality-template", - "version": "1.0.2", + "version": "1.0.8", "private": true, "type": "module", "engines": { diff --git a/tools/quality/run.mjs b/tools/quality/run.mjs index e0b21ae..17e3c74 100644 --- a/tools/quality/run.mjs +++ b/tools/quality/run.mjs @@ -69,6 +69,14 @@ function unused(config, production) { function duplicates(config) { if (!config.duplicatePaths?.length) throw new Error('duplicatePaths must list authored runtime/tooling roots'); + if (config.duplicateCanonicalFormat) { + const { report } = analyze( + process.execPath, + [join(directory, 'canonical-duplicates.mjs'), JSON.stringify(config)], + 'Canonical jscpd', + ); + return { findings: duplicateRecords(report), report }; + } const output = mkdtempSync(join(tmpdir(), '1msg-jscpd-')); try { const argv = [ diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json index 444e17d..da93308 100644 --- a/tools/quality/template-manifest.json +++ b/tools/quality/template-manifest.json @@ -1,23 +1,27 @@ { "schemaVersion": 1, - "version": "1.0.2", + "version": "1.0.8", "files": { - "README.md": "1d3f6f9d420adea402d92aff483c14271e6e24c291437d6ea5b59c3162702a20", + "README.md": "e74940b5acec1bdbff75eb751432967630ddb4215af24d89d31dd3694916c12e", + "canonical-duplicates.mjs": "a3583fdc3e344af448ea8d2543c2398daaa03fa10a0739da486afb04e35425ba", + "complexity.mjs": "4ed5553c392621e0615a48c12e12300c8602ed2a28cfbaff67002acf82e49cac", "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", "lib/baseline.mjs": "7876ba90b80448d9c9003c21e348095ed22630c41fc26ed944984742020549dd", "lib/git.mjs": "b7c26871526d864bf8d12f01c613d3bfa0adb2da9d072544d8f09407ef598758", - "lib/guards.mjs": "310c224c5d072fa16b1cf5f0c47e5da4258f0f63fa9a1c4dc114c9fe192bc398", - "lib/historical.mjs": "d338d88bae6d1da19f27296fbb6c57cff4ca09664fe7baa8d6c8d801ca3e69f2", + "lib/guards.mjs": "e94dc6b58703b44420f8b815ee069b9e0a7fa9aefd5faba63d55f1c3da7c4286", + "lib/historical.mjs": "43b46395828daa3f19d8692e9bd22ea6cfc1d0dbac83814d727894f672a0ddd2", "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", - "lib/reports.mjs": "f47f6cbf8022691e61a245bf54a5fdd1ba9f2037906ec6576f2ac771224161dc", + "lib/reports.mjs": "60e78d58256d1060067e939397c8760384f202625c394f73d18e3311ccabb44c", "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", - "package-lock.json": "931d28ffff6590892a072569df9c57345d0a388a22598b3482dee53136a52828", - "package.json": "b2c70073c423135e4b5abba9507d58fd5136a676339e816b72d6dd4bcbb1b757", + "package-lock.json": "fc4279a0f1393109958815b6b92fc95acd1c5a98387ea6d3f13a61a9aeba8a60", + "package.json": "3e9ef4c922c64deddd6c2c50350def2bf79cd0354af891e5d7051c082c4d4937", "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", - "run.mjs": "b60c0fc2419c8cfd32eddf369da38b2d87e2b7eacbc31fda31c598930900f199", + "run.mjs": "7cf26128cdf63f3a7ccab7341a0a274a352fd9bda0521ba41e37216bb9cc249f", "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", - "test/cli.test.mjs": "f743a18f0763cf5b5f42f8d2a4b71f67a4de900a3955a299309395af95b99cf3", - "test/ratchet.test.mjs": "62fef1cc7a1851db81c30966909968ff84637b8ed8003821120269c4fae70d49", + "test/cli.test.mjs": "64dda5d60ef9fd2d444f96b2623b97f6197917f1e121aaf73cbe1dfeff90a8ef", + "test/complexity.test.mjs": "ba1f702ba94de3fcad93cb5e43a49bc2456be1426c81754149420d210f2b3952", + "test/ratchet.test.mjs": "324a932c5a52d1b037e111042e1b41e5686f8d4dbfd0307faf86cee649ebc27a", + "test/reports.test.mjs": "d75a93ee4dc606d9930c3a1e19912e093e8635910a7c21f81c735e209c03835f", "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", "tsconfig.node.json": "627661abcb7e992c4bfaf98d6e68a12678573b5d4f6e821ea0fa43fa6e233f28", "tsconfig.svelte.json": "5777247ea98aaf2d886b87cd12206a641377edcdd086ce5fd5b58adc6f0bc771" diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs index 897d9cd..624b8ec 100644 --- a/tools/quality/test/cli.test.mjs +++ b/tools/quality/test/cli.test.mjs @@ -508,3 +508,244 @@ test('historical Knip removes a current-only exact vendor ignore without relaxin f.close(); } }); + +/** Pinned formatting defines identical clone units for old and current source, while a new participant still fails the real gate. */ +test('canonical jscpd CLI preserves formatting-only debt and rejects a new clone', () => { + const f = fixture(); + try { + f.write( + 'quality.config.mjs', + `export default { schemaVersion: 1, profile: 'A', defaultBranch: 'main', sourceRoots: ['src'], duplicatePaths: ['src'], duplicateCanonicalFormat: true, duplicateFormats: ['javascript', 'typescript', 'jsx', 'tsx'], duplicateIgnore: [], duplicateMaxPercentage: 100 };\n`, + ); + const source = + 'export function calculate() { const label = "ready"; let value = 0; ' + + Array.from({ length: 20 }, (_, i) => `value += ${i};`).join('') + + 'return { label, value }; }'; + f.write('src/a.js', source); + f.write('src/b.js', source); + const base = f.commit(); + const initial = f.run( + 'duplicates', + '--base', + base, + '--bootstrap', + '--owner', + 'quality-fixture', + '--expires', + '2099-12-31', + '--reason', + 'Historical clone fixture', + '--issue', + 'https://example.invalid/quality', + ); + assert.equal(initial.status, 0, initial.stderr); + const baseline = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/duplicates.json'), 'utf8'), + ); + assert.ok(baseline.entries.length > 0); + f.write( + 'src/a.js', + source.replaceAll(';', ';\n').replaceAll('"ready"', "'ready'"), + ); + const formatted = f.run('duplicates', '--base', base); + assert.equal(formatted.status, 0, formatted.stderr); + f.write('src/c.js', source); + const growth = f.run('duplicates', '--base', base); + assert.notEqual(growth.status, 0); + assert.match(growth.stderr, /New or increased|new\/increased/); + } finally { + f.close(); + } +}); + +/** Invalid syntax or a framework file without its formatter must fail canonical analysis instead of disappearing from coverage. */ +test('canonical jscpd fails closed for unsupported or malformed source', () => { + const f = fixture(); + try { + f.write( + 'quality.config.mjs', + `export default { schemaVersion: 1, profile: 'A', defaultBranch: 'main', sourceRoots: ['src'], duplicatePaths: ['src'], duplicateCanonicalFormat: true, duplicateIgnore: [], duplicateMaxPercentage: 100 };\n`, + ); + f.write('src/index.js', 'export const value = 1;'); + const base = f.commit(); + f.write('src/index.js', 'export const value = ;'); + assert.notEqual(f.run('duplicates', '--base', base).status, 0); + f.write('src/index.js', 'export const value = 1;'); + f.write( + 'src/Widget.svelte', + '

{value}

', + ); + const unsupported = f.run('duplicates', '--base', base); + assert.notEqual(unsupported.status, 0); + assert.match(unsupported.stderr, /framework formatter/); + } finally { + f.close(); + } +}); + +/** Current test-runner config is an analyzer input; historical application and test source must still come only from Git. */ +test('historical replay uses current Jest config without replacing trusted source', () => { + const f = fixture(); + try { + f.write('src/index.js', 'export const value = "historical";\n'); + f.write('jest.config.cjs', 'module.exports = { rootDir: "old" };\n'); + const base = f.commit(); + f.write('src/index.js', 'export const value = "current-only";\n'); + f.write('jest.config.cjs', 'module.exports = { rootDir: __dirname };\n'); + const historical = new URL('../lib/historical.mjs', import.meta.url).href; + const template = fileURLToPath(new URL('../', import.meta.url)); + const script = `import { historicalAnalysis } from ${JSON.stringify(historical)}; + import { readFileSync, existsSync } from 'node:fs'; + const value = historicalAnalysis(${JSON.stringify(base)}, {knipConfig:'knip.json'}, ${JSON.stringify(template)}, () => ({ + config: readFileSync('jest.config.cjs','utf8'), + source: readFileSync('src/index.js','utf8'), + newSource: existsSync('src/current-only.js') + })); process.stdout.write(JSON.stringify(value));`; + f.write( + 'src/current-only.js', + 'throw new Error("must not enter historical source");\n', + ); + const result = spawnSync( + process.execPath, + ['--input-type=module', '-e', script], + { cwd: f.cwd, encoding: 'utf8', timeout: 15000 }, + ); + assert.equal(result.status, 0, result.stderr); + const replay = JSON.parse(result.stdout); + assert.match(replay.config, /__dirname/); + assert.match(replay.source, /historical/); + assert.equal(replay.newSource, false); + } finally { + f.close(); + } +}); + +/** A fixed early callback cannot renumber later debt or lend its larger allowance to a different growing callback. */ +test('actual complexity CLI binds callback allowances to lexical owners', () => { + const f = fixture(); + try { + const preset = new URL('../eslint.mjs', import.meta.url).href; + f.write( + 'eslint.config.mjs', + `import { maintainabilityConfig, tseslint } from '${preset}'; export default [{languageOptions:{parser:tseslint.parser}}, ...maintainabilityConfig(), {rules:{complexity:['error',2]}}];`, + ); + const earlier = + 'const earlier = wrap((value) => { if (value.a) return 1; if (value.b) return 2; if (value.c) return 3; if (value.d) return 4; if (value.e) return 5; return 0; });'; + const later = + 'const later = wrap((value) => { if (value.a) return 1; if (value.b) return 2; return 0; });'; + f.write('src/index.js', `${earlier}\n${later}`); + const base = f.commit(); + const args = [ + 'report', + '--kind', + 'eslint', + '--base', + base, + '--bootstrap', + '--owner', + 'quality-fixture', + '--expires', + '2099-12-31', + '--reason', + 'Historical callback debt', + '--issue', + 'TEST-1', + '--', + process.execPath, + fileURLToPath(new URL('../complexity.mjs', import.meta.url)), + '--config', + 'eslint.config.mjs', + 'src/index.js', + ]; + const original = f.run(...args); + assert.equal(original.status, 0, original.stderr); + const originalBaseline = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.deepEqual( + originalBaseline.entries.map(({ value }) => value).sort(), + [3, 6], + ); + f.write( + 'src/index.js', + `const earlier = wrap((value) => value);\n${later}`, + ); + const fixed = f.run(...args); + assert.equal(fixed.status, 0, fixed.stderr); + const reducedBaseline = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.equal(reducedBaseline.entries.length, 1); + assert.equal( + reducedBaseline.entries[0].key, + originalBaseline.entries.find(({ value }) => value === 3).key, + ); + f.write( + 'src/index.js', + `const earlier = wrap((value) => value);\n${later.replace('return 0;', 'if (value.c) return 3; return 0;')}`, + ); + const growth = f.run(...args); + assert.equal(growth.status, 1, growth.stderr); + assert.match( + growth.stderr, + /Cannot baseline a new\/increased finding.*later/, + ); + } finally { + f.close(); + } +}); + +/** Class field initializers and static blocks are independent ESLint code paths and must keep their class ownership. */ +test('actual complexity CLI resolves class field and static block scopes', () => { + const f = fixture(); + try { + const preset = new URL('../eslint.mjs', import.meta.url).href; + f.write( + 'eslint.config.mjs', + `import { maintainabilityConfig, tseslint } from '${preset}'; export default [{languageOptions:{parser:tseslint.parser}}, ...maintainabilityConfig(), {rules:{complexity:['error',2]}}];`, + ); + f.write( + 'src/index.js', + `class First { + value = ready ? (active ? 1 : 2) : 3; + static { if (ready) start(); if (active) finish(); } + } + class Second { + value = ready ? (active ? 1 : 2) : 3; + static { if (ready) start(); if (active) finish(); } + }`, + ); + const base = f.commit(); + const result = f.run( + 'report', + '--kind', + 'eslint', + '--base', + base, + '--bootstrap', + '--owner', + 'quality-fixture', + '--expires', + '2099-12-31', + '--reason', + 'Historical class initializer debt', + '--issue', + 'TEST-1', + '--', + process.execPath, + fileURLToPath(new URL('../complexity.mjs', import.meta.url)), + '--config', + 'eslint.config.mjs', + 'src/index.js', + ); + assert.equal(result.status, 0, result.stderr); + const baseline = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.equal(baseline.entries.length, 4); + assert.equal(new Set(baseline.entries.map(({ key }) => key)).size, 4); + assert.ok(baseline.entries.every(({ value }) => value === 3)); + } finally { + f.close(); + } +}); diff --git a/tools/quality/test/complexity.test.mjs b/tools/quality/test/complexity.test.mjs new file mode 100644 index 0000000..ccf0730 --- /dev/null +++ b/tools/quality/test/complexity.test.mjs @@ -0,0 +1,247 @@ +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { + mkdtempSync, + writeFileSync, + readFileSync, + rmSync, + symlinkSync, +} from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import test from 'node:test'; +import { fileURLToPath } from 'node:url'; +import { runInNewContext } from 'node:vm'; + +import ts from 'typescript'; + +/** Run the shipped CLI against a disposable source file with real maintainability rules. */ +function fixture(t) { + const root = mkdtempSync(join(tmpdir(), 'canonical-complexity-')); + t.after(() => rmSync(root, { recursive: true, force: true })); + const preset = new URL('../eslint.mjs', import.meta.url).href; + writeFileSync( + join(root, 'eslint.config.mjs'), + `import { maintainabilityConfig, tseslint } from '${preset}'; export default [{languageOptions:{parser:tseslint.parser}}, ...maintainabilityConfig()];`, + ); + const cli = join(root, 'quality-complexity.mjs'); + symlinkSync( + fileURLToPath(new URL('../complexity.mjs', import.meta.url)), + cli, + ); + /** Preserve analyzer exit status and JSON rather than treating a missing report as an empty finding list. */ + return (source, fileName = 'source.js') => { + writeFileSync(join(root, fileName), source); + const result = spawnSync( + process.execPath, + [cli, '--config', 'eslint.config.mjs', fileName], + { cwd: root, encoding: 'utf8', timeout: 15000 }, + ); + assert.equal(readFileSync(join(root, fileName), 'utf8'), source); + return result; + }; +} + +/** Whitespace-only growth is neutral, while an actual extra statement still increases the measured function. */ +test('canonical CLI uses identical units for historical and current line debt', (t) => { + const run = fixture(t); + const statements = Array.from({ length: 80 }, () => 'value += 1;'); + const compact = `export function count() { let value = 0; ${statements.join('')} return value; }`; + const expanded = `export function count() {\n\nlet value = 0;\n${statements.join('\n\n')}\nreturn value;\n}`; + const original = run(compact), + whitespace = run(expanded); + assert.equal(original.status, 1, original.stderr); + assert.equal(whitespace.status, 1, whitespace.stderr); + const [before] = JSON.parse(original.stdout), + [after] = JSON.parse(whitespace.stdout); + assert.equal( + before.source + .split('\n') + .filter((line) => line.trim()) + .join('\n'), + after.source + .split('\n') + .filter((line) => line.trim()) + .join('\n'), + ); + assert.deepEqual( + before.messages.map(({ ruleId, message }) => ({ ruleId, message })), + after.messages.map(({ ruleId, message }) => ({ ruleId, message })), + ); + const growth = run( + compact.replace('return value;', 'value += 2; return value;'), + ); + assert.equal(growth.status, 1, growth.stderr); + const [increased] = JSON.parse(growth.stdout); + assert.notDeepEqual(increased.messages, before.messages); + assert.ok( + increased.source.split('\n').length > before.source.split('\n').length, + ); +}); + +/** A formatter/parser error is a failed analyzer, never a zero-debt report or a baselinable diagnostic. */ +test('canonical CLI fails closed for invalid syntax', (t) => { + const result = fixture(t)('export function broken( {'); + assert.equal(result.status, 2); + assert.equal(result.stdout, ''); + assert.ok(result.stderr.length > 0); +}); + +/** Source directives cannot hide measured debt, and unrelated historical framework directives cannot become parser diagnostics. */ +test('canonical CLI ignores inline configuration on both metric inputs', (t) => { + const run = fixture(t); + const body = `export function count() { let value = 0; ${Array.from({ length: 80 }, () => 'value += 1;').join('')} return value; }`; + const plain = run(body); + const annotated = run( + '/* eslint-disable unknown-framework/legacy-rule, max-lines-per-function */\n' + + body, + ); + assert.equal(plain.status, 1, plain.stderr); + assert.equal(annotated.status, 1, annotated.stderr); + const select = (result) => + JSON.parse(result.stdout).flatMap((file) => + file.messages.map(({ ruleId, message }) => ({ ruleId, message })), + ); + assert.deepEqual(select(annotated), select(plain)); + assert.ok( + select(annotated).some((item) => item.ruleId === 'max-lines-per-function'), + ); +}); + +/** Execute canonical TS/JSX through the same compiler settings to compare literals, child text and evaluation order. */ +function evaluate(source, fileName) { + const compiled = ts.transpileModule(source, { + fileName, + compilerOptions: { + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.None, + jsx: ts.JsxEmit.React, + jsxFactory: 'element', + }, + }); + const context = {}; + runInNewContext(compiled.outputText, context, { timeout: 1000 }); + return JSON.parse(context.result); +} + +/** Callback documentation and JSX comments cannot change file/function line debt; actual instructions must still grow it. */ +test('canonical CLI strips JSX documentation before measuring wrapped line debt', (t) => { + const run = fixture(t); + const statements = Array.from({ length: 160 }, () => 'value += 1;').join( + '\n', + ); + const declarations = Array.from( + { length: 350 }, + (_, index) => `export const field${index} = ${index};`, + ).join('\n'); + const plain = `export function Card() { + let value = 0; + ${statements} + return
{field.label}
} />; + } + ${declarations}`; + const documented = plain + .replace( + 'export function', + '/** Render the editable panel and preserve its accumulated count. */\nexport function', + ) + .replace( + 'render={', + 'render={/** Provide the field label and accessible description to the panel. */ ', + ) + .replace( + '', + '{/* Keep the visible label inside the field container. */}', + ) + .replace( + 'value += 1;', + 'value += /* Increment the visible count once. */ 1;', + ); + const original = run(plain, 'source.tsx'); + const annotated = run(documented, 'source.tsx'); + assert.equal(original.status, 1, original.stderr); + assert.equal(annotated.status, 1, annotated.stderr); + const [before] = JSON.parse(original.stdout); + const [after] = JSON.parse(annotated.stdout); + assert.equal(after.source, before.source); + assert.deepEqual(after.messages, before.messages); + assert.ok(before.messages.some(({ ruleId }) => ruleId === 'max-lines')); + assert.ok( + before.messages.some(({ ruleId }) => ruleId === 'max-lines-per-function'), + ); + const growth = run( + documented.replace('let value = 0;', 'let value = 0; value += 2;'), + 'source.tsx', + ); + assert.equal(growth.status, 1, growth.stderr); + const [increased] = JSON.parse(growth.stdout); + assert.notDeepEqual( + increased.messages.map(({ ruleId, message }) => ({ ruleId, message })), + before.messages.map(({ ruleId, message }) => ({ ruleId, message })), + ); +}); + +/** Comment-like literals and rendered JSX text/element order survive printing; adjacent text nodes are normalized like DOM content. */ +test('canonical CLI preserves string, tagged-template and JSX semantics', (t) => { + const source = [ + `function element(type, props, ...children) { + const rendered = []; + for (const child of children) { + const previous = rendered.length - 1; + if (typeof child === 'string' && typeof rendered[previous] === 'string') rendered[previous] += child; + else rendered.push(child); + } + return {type, props, children: rendered}; + }`, + 'const value = "https://example.invalid/a/*literal*/";', + 'const raw = String.raw`line\\n/* literal */ ${value} // end`;', + 'const cooked = `first\nsecond ${value}`;', + String.raw`const expression = /\/\*literal\*\//u;`, + 'const node =
leading {/* actual comment */}{value} trailing
;', + 'globalThis.result = JSON.stringify({value, raw, cooked, matches: expression.test(value), node});', + ].join('\n'); + const result = fixture(t)(source, 'source.tsx'); + assert.equal(result.status, 0, result.stderr); + const [report] = JSON.parse(result.stdout); + assert.deepEqual( + evaluate(report.source, 'source.tsx'), + evaluate(source, 'source.tsx'), + ); + assert.equal( + evaluate(report.source, 'source.tsx').node.props.title, + '/* attribute */', + ); + assert.match(evaluate(report.source, 'source.tsx').raw, /line\\n/); +}); + +/** Comments near automatic semicolon insertion and adjacent unary operators cannot change executable statements. */ +test('canonical CLI preserves automatic-semicolon and operator semantics', (t) => { + const source = `function returned() { + return /* Preserve the original newline after return. */ + 42; + } + const sum = 1 + /* Keep the unary plus separate. */ +2; + globalThis.result = JSON.stringify({isUndefined: returned() === undefined, sum});`; + const result = fixture(t)(source); + assert.equal(result.status, 0, result.stderr); + const [report] = JSON.parse(result.stdout); + assert.deepEqual(evaluate(report.source, 'source.js'), { + isUndefined: true, + sum: 3, + }); + assert.deepEqual( + evaluate(report.source, 'source.js'), + evaluate(source, 'source.js'), + ); +}); + +/** Invalid TSX remains an analyzer failure even though the TypeScript printer can emit a recovered syntax tree. */ +test('canonical CLI fails closed before printing a recovered TSX tree', (t) => { + const result = fixture(t)( + 'export const view =
{/* valid comment */}
;', + 'source.tsx', + ); + assert.equal(result.status, 2); + assert.equal(result.stdout, ''); + assert.match(result.stderr, /Complexity parse failed/); +}); diff --git a/tools/quality/test/ratchet.test.mjs b/tools/quality/test/ratchet.test.mjs index 7722924..fc2376c 100644 --- a/tools/quality/test/ratchet.test.mjs +++ b/tools/quality/test/ratchet.test.mjs @@ -193,7 +193,7 @@ test('whole-file line limits keep their identity when the diagnostic moves betwe ], }, ])[0]; - assert.equal(finding(20).key, 'lib/guards.mjs|max-lines||0'); + assert.equal(finding(20).key, 'lib/guards.mjs|max-lines|'); assert.equal(finding(120).key, finding(20).key); }); @@ -236,3 +236,29 @@ test('suppression gates do not mistake strings for directives', () => { 0, ); }); + +/** Formatting within template expressions and a chained call must not invent a new function or callback. */ +test('documentation identities preserve template-expression context and stable call chains', () => { + const before = + 'describe("groupIntoBlocks",()=>{it("splits a parent",()=>{const value=Array.from({length:3},(_,i)=>({key:`p.k${i}`,text:`Text ${i}`}));return value;});});'; + const after = + "describe('groupIntoBlocks', () => {\n it('splits a parent', () => {\n const value = Array.from({length:3}, (_, i) => ({\n key: `p.k${i}`,\n text: `Text ${i}`,\n })); return value;\n });\n});"; + const identity = (source) => + functionsIn('src/a.ts', source).map(({ key, signature }) => ({ + key, + signature, + })); + assert.deepEqual(identity(before), identity(after)); + assert.notDeepEqual( + identity(before), + identity(before.replace('Text ${i}', 'Different ${i}')), + ); + const chained = 'prefetch({ value: 1 }).catch(() => { recover(); });'; + const documented = + 'prefetch({ /** Explain the input. */ value: 1, }).catch(() => { recover(); });'; + assert.deepEqual(identity(chained), identity(documented)); + assert.notDeepEqual( + identity(chained), + identity(chained.replace('prefetch', 'send')), + ); +}); diff --git a/tools/quality/test/reports.test.mjs b/tools/quality/test/reports.test.mjs new file mode 100644 index 0000000..68c39e2 --- /dev/null +++ b/tools/quality/test/reports.test.mjs @@ -0,0 +1,192 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import { ESLint } from 'eslint'; + +import { eslintRecords } from '../lib/reports.mjs'; + +/** Generate real small-fixture diagnostics with low thresholds without changing the shipped policy. */ +async function analyze(source, rule = 'complexity', limit = 2) { + const eslint = new ESLint({ + overrideConfigFile: true, + overrideConfig: [ + { + languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } }, + rules: { [rule]: ['error', limit] }, + }, + ], + }); + const reports = await eslint.lintText(source, { filePath: 'fixture.js' }); + assert.equal(reports.length, 1); + assert.equal(reports[0].fatalErrorCount, 0); + return reports.map((report) => ({ + ...report, + filePath: 'fixture.js', + source, + })); +} + +/** Vary callback bodies while retaining their call site to probe allowance transfer rather than report counts. */ +function callback(branches, result = '0') { + return `(value) => { ${Array.from({ length: branches }, (_, index) => `if (value.p${index}) return ${index + 1};`).join(' ')} return ${result}; }`; +} + +/** Resolve the real analyzer report to stable keys, preserving parser and ambiguity failures. */ +async function findings(source, rule, limit) { + return eslintRecords(await analyze(source, rule, limit)); +} + +/** Variables and object/JSX properties name anonymous callbacks even when their containing call is unchanged. */ +test('callback identities retain all named variable and property owners', async () => { + const before = `const first = wrap(${callback(2)}); const second = wrap(${callback(3)}); + const options = { load: wrap(${callback(2)}), save: wrap(${callback(3)}) }; + const view = ;`; + const original = await findings(before); + assert.equal(original.length, 6); + assert.equal(new Set(original.map(({ key }) => key)).size, 6); + const current = await findings(before.replaceAll(callback(2), callback(0))); + assert.equal(current.length, 3); + assert.deepEqual( + current, + original.filter(({ value }) => value === 4), + ); +}); + +/** Method names alone cannot move allowances across class, instance/static, or enclosing function boundaries. */ +test('same method and nested function names keep class and function ownership', async () => { + const before = `class First { handle(value) { if (value.a) return 1; if (value.b) return 2; return 0; } + static handle(value) { if (value.a) return 1; if (value.b) return 2; if (value.c) return 3; return 0; } } + class Second { handle(value) { if (value.a) return 1; if (value.b) return 2; if (value.c) return 3; return 0; } } + function left() { function nested(value) { if (value.a) return 1; if (value.b) return 2; return 0; } return nested; } + function right() { function nested(value) { if (value.a) return 1; if (value.b) return 2; if (value.c) return 3; return 0; } return nested; }`; + const original = await findings(before); + assert.equal(original.length, 5); + const reduced = before.replaceAll( + 'if (value.a) return 1; if (value.b) return 2; return 0;', + 'return value;', + ); + assert.deepEqual( + await findings(reduced), + original.filter(({ value }) => value === 4), + ); +}); + +/** The call target and argument index distinguish callbacks without depending on another diagnostic's presence or order. */ +test('call targets and argument positions distinguish unnamed callbacks', async () => { + const source = `left.accept(${callback(2)}, ${callback(3)}); right.accept(${callback(2)});`; + const report = await analyze(source); + const original = eslintRecords(report); + assert.equal(original.length, 3); + const reordered = report.map((file) => ({ + ...file, + messages: [...file.messages].reverse(), + })); + assert.deepEqual(eslintRecords(reordered), original); + const reduced = source.replace( + `left.accept(${callback(2)},`, + `left.accept(${callback(0)},`, + ); + assert.deepEqual( + await findings(reduced), + original.filter( + ({ key, value }) => !(key.includes('"left"') && value === 3), + ), + ); +}); + +/** Identical caller/name chains require the whole sibling group as evidence, including callbacks currently below the limit. */ +test('ambiguous groups cannot borrow another callback body allowance', async () => { + const before = `run(${callback(5)}); run(${callback(2)});`; + const oldKeys = new Set((await findings(before)).map(({ key }) => key)); + const after = `run(${callback(0)}); run(${callback(5)});`; + const current = await findings(after); + assert.equal(current.length, 1); + assert.ok(current.every(({ key }) => !oldKeys.has(key))); + const belowThreshold = `run(${callback(0)}); run(${callback(2)});`; + const prior = await findings(belowThreshold); + const changedSibling = await findings( + `run(${callback(1)}); run(${callback(2)});`, + ); + assert.notEqual(prior[0].key, changedSibling[0].key); + const originalOrder = await findings( + `run(${callback(5)}); run(${callback(0)});`, + ); + const swappedBodies = await findings( + `run(${callback(0)}); run(${callback(5)});`, + ); + assert.notEqual(originalOrder[0].key, swappedBodies[0].key); +}); + +/** Formatting and comments leave ambiguous syntax fingerprints stable; literal/template/JSX content remains meaningful evidence. */ +test('ambiguous fingerprints preserve source semantics and ignore comments', async () => { + const first = callback(2, '`first ${value.name}`'); + const second = callback(2, 'second'); + const source = `run(${first}); run(${second});`; + const original = await findings(source); + assert.equal(original.length, 2); + assert.deepEqual( + await findings(source.replaceAll('if (', '/* Condition */\nif (')), + original, + ); + const changed = await findings( + source.replace('first ${value.name}', 'changed ${value.name}'), + ); + assert.ok( + changed.every(({ key }) => !original.some((entry) => entry.key === key)), + ); + const jsxChanged = await findings(source.replace('>second<', '>different<')); + assert.ok( + jsxChanged.every(({ key }) => !original.some((entry) => entry.key === key)), + ); +}); + +/** Equal bodies under the same lexical owner have no trustworthy correspondence, and duplicate reports cannot invent an ordinal fallback. */ +test('indistinguishable callbacks and duplicate diagnostics fail closed', async () => { + await assert.rejects( + () => findings(`run(${callback(2)}); run(${callback(2)});`), + /Ambiguous lexical scope/, + ); + const reports = await analyze(`const handler = wrap(${callback(2)});`); + reports[0].messages.push(reports[0].messages[0]); + assert.throws( + () => eslintRecords(reports), + /Duplicate ESLint diagnostic identity/, + ); +}); + +/** Separate deep branches have independent syntax owners, so a function cannot lend its deepest block's allowance to another block. */ +test('nested depth reports are keyed by syntax instead of diagnostic ordinal', async () => { + const source = + 'function check(value) { if (value.a) { if (value.b) { if (value.c) return 1; } } if (value.d) { if (value.e) { if (value.f) { if (value.g) return 2; } } } }'; + const records = await findings(source, 'max-depth', 2); + assert.ok(records.length > 1); + assert.equal(new Set(records.map(({ key }) => key)).size, records.length); +}); + +/** Recovered ASTs and missing function locations cannot silently attach findings to file-level debt. */ +test('invalid or missing scope evidence fails closed', () => { + const message = { + ruleId: 'complexity', + message: 'Arrow function has a complexity of 3. Maximum allowed is 2.', + line: 1, + column: 1, + }; + assert.throws( + () => + eslintRecords([ + { filePath: 'missing.js', source: '', messages: [message] }, + ]), + /No lexical scope/, + ); + assert.throws( + () => + eslintRecords([ + { + filePath: 'invalid.js', + source: 'function broken( {', + messages: [message], + }, + ]), + /Invalid syntax/, + ); +}); From 6d0f78ad3779a7afbdddd17c00de919b8efc1115 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 01:03:16 +0500 Subject: [PATCH 4/8] ci(quality): seal lexical scope regression fixes --- tools/quality/README.md | 12 ++++- tools/quality/lib/reports.mjs | 26 +++++++++- tools/quality/package-lock.json | 4 +- tools/quality/package.json | 2 +- tools/quality/template-manifest.json | 14 +++--- tools/quality/test/cli.test.mjs | 74 ++++++++++++++++++++++++++++ tools/quality/test/reports.test.mjs | 46 +++++++++++++++++ 7 files changed, 165 insertions(+), 13 deletions(-) diff --git a/tools/quality/README.md b/tools/quality/README.md index 4b600bd..aa67e5b 100644 --- a/tools/quality/README.md +++ b/tools/quality/README.md @@ -1,4 +1,4 @@ -# 1MSG quality template 1.0.8 +# 1MSG quality template 1.0.9 Vendored, private template for 1MSG-156. Install its exact tools with `npm --prefix tools/quality ci` on Node 24.19.0. The lockfile and @@ -108,3 +108,13 @@ or indistinguishable groups fail closed. The real CLI fixtures verify both legitimate debt reduction and rejection of transferred/increased allowances. Existing consumers must replay historical source with this version when adopting the new key schema; old diagnostic ordinals are never silently migrated. + +## 1.0.9 migration + +Complexity identities now retain lexical `for`, `for-in` and `for-of` headers +(binding, source/condition/increment and `await` mode). Identical statements in +different loops no longer collide. Loop bodies, source lines and diagnostic +ordinals do not identify allowances; indistinguishable sibling loops still fail +closed. Consumers must replay their original trusted adoption base with the +updated analyzer, preserving debt owners, deadlines and reasons. Do not translate +baseline keys manually or renew historical debt as part of the version update. diff --git a/tools/quality/lib/reports.mjs b/tools/quality/lib/reports.mjs index b04abef..b70336f 100644 --- a/tools/quality/lib/reports.mjs +++ b/tools/quality/lib/reports.mjs @@ -244,7 +244,7 @@ function ownerName(node, source) { return ['computed', syntaxFingerprint(node, source)]; } -/** Include every named lexical owner and each enclosing call's argument position, without using source lines or diagnostic order. */ +/** Include named owners, lexical loop bindings and call argument positions without source lines or diagnostic order. */ function lexicalOwners(node, source) { const owners = []; let child; @@ -253,7 +253,29 @@ function lexicalOwners(node, source) { current && !ts.isSourceFile(current); current = current.parent ) { - if (ts.isCallExpression(current) || ts.isNewExpression(current)) { + if (ts.isForOfStatement(current) || ts.isForInStatement(current)) { + owners.push([ + ts.SyntaxKind[current.kind], + syntaxFingerprint(current.initializer, source), + syntaxFingerprint(current.expression, source), + ts.isForOfStatement(current) && current.awaitModifier + ? 'await' + : 'sync', + child === current.statement ? 'body' : 'header', + ]); + } else if (ts.isForStatement(current)) { + owners.push([ + ts.SyntaxKind[current.kind], + current.initializer + ? syntaxFingerprint(current.initializer, source) + : null, + current.condition ? syntaxFingerprint(current.condition, source) : null, + current.incrementor + ? syntaxFingerprint(current.incrementor, source) + : null, + child === current.statement ? 'body' : 'header', + ]); + } else if (ts.isCallExpression(current) || ts.isNewExpression(current)) { const argument = current.arguments?.indexOf(child) ?? -1; owners.push([ ts.SyntaxKind[current.kind], diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json index 8ad5519..0c6a588 100644 --- a/tools/quality/package-lock.json +++ b/tools/quality/package-lock.json @@ -1,12 +1,12 @@ { "name": "@1msg/quality-template", - "version": "1.0.8", + "version": "1.0.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@1msg/quality-template", - "version": "1.0.8", + "version": "1.0.9", "dependencies": { "@eslint/js": "9.39.5", "dependency-cruiser": "18.6.0", diff --git a/tools/quality/package.json b/tools/quality/package.json index b71d5b0..0620fb9 100644 --- a/tools/quality/package.json +++ b/tools/quality/package.json @@ -1,6 +1,6 @@ { "name": "@1msg/quality-template", - "version": "1.0.8", + "version": "1.0.9", "private": true, "type": "module", "engines": { diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json index da93308..883a990 100644 --- a/tools/quality/template-manifest.json +++ b/tools/quality/template-manifest.json @@ -1,8 +1,8 @@ { "schemaVersion": 1, - "version": "1.0.8", + "version": "1.0.9", "files": { - "README.md": "e74940b5acec1bdbff75eb751432967630ddb4215af24d89d31dd3694916c12e", + "README.md": "91dd028828d08424d26dd4f5fc1e91da5c2258a3604a2fab57658c0f1c59b745", "canonical-duplicates.mjs": "a3583fdc3e344af448ea8d2543c2398daaa03fa10a0739da486afb04e35425ba", "complexity.mjs": "4ed5553c392621e0615a48c12e12300c8602ed2a28cfbaff67002acf82e49cac", "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", @@ -11,17 +11,17 @@ "lib/guards.mjs": "e94dc6b58703b44420f8b815ee069b9e0a7fa9aefd5faba63d55f1c3da7c4286", "lib/historical.mjs": "43b46395828daa3f19d8692e9bd22ea6cfc1d0dbac83814d727894f672a0ddd2", "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", - "lib/reports.mjs": "60e78d58256d1060067e939397c8760384f202625c394f73d18e3311ccabb44c", + "lib/reports.mjs": "e41c4994e444128ae0418eff7240f49de678a97112fa7d5171fbe680d26b6dff", "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", - "package-lock.json": "fc4279a0f1393109958815b6b92fc95acd1c5a98387ea6d3f13a61a9aeba8a60", - "package.json": "3e9ef4c922c64deddd6c2c50350def2bf79cd0354af891e5d7051c082c4d4937", + "package-lock.json": "314de2cb801a00bb42240da3567274bac9725359c0429665c505653a51bf5f91", + "package.json": "e1228b0144b1d8bd79283bfacec0be9a54f636e973ba42de4b1cc3694972f57e", "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", "run.mjs": "7cf26128cdf63f3a7ccab7341a0a274a352fd9bda0521ba41e37216bb9cc249f", "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", - "test/cli.test.mjs": "64dda5d60ef9fd2d444f96b2623b97f6197917f1e121aaf73cbe1dfeff90a8ef", + "test/cli.test.mjs": "63350dcf9c58c0e41d0dcc49bb8b9eef8dd0c01e781f25a58490f1476f58e94a", "test/complexity.test.mjs": "ba1f702ba94de3fcad93cb5e43a49bc2456be1426c81754149420d210f2b3952", "test/ratchet.test.mjs": "324a932c5a52d1b037e111042e1b41e5686f8d4dbfd0307faf86cee649ebc27a", - "test/reports.test.mjs": "d75a93ee4dc606d9930c3a1e19912e093e8635910a7c21f81c735e209c03835f", + "test/reports.test.mjs": "3d5be0312d4870dd00e4cdafaa422d1e0d4e0d3ecaf4dc65a73a4dac577bfbfa", "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", "tsconfig.node.json": "627661abcb7e992c4bfaf98d6e68a12678573b5d4f6e821ea0fa43fa6e233f28", "tsconfig.svelte.json": "5777247ea98aaf2d886b87cd12206a641377edcdd086ce5fd5b58adc6f0bc771" diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs index 624b8ec..33425a7 100644 --- a/tools/quality/test/cli.test.mjs +++ b/tools/quality/test/cli.test.mjs @@ -749,3 +749,77 @@ test('actual complexity CLI resolves class field and static block scopes', () => f.close(); } }); + +/** A Make-shaped source has equal if statements in separate loops; trusted replay retains only the precise old depth allowance. */ +test('actual raw complexity CLI distinguishes lexical loops and rejects depth transfer', () => { + const f = fixture(); + try { + f.write( + 'eslint.config.mjs', + "export default [{rules:{'max-depth':['error',3]}}];", + ); + const shallow = + 'for (const ack of root.ack) { const item = record(ack); if (item) found.push(statusEvent(item)); }'; + const deep = + 'for (const entry of root.entry) { for (const change of entry.changes) { for (const status of change.statuses) { const item = record(status); if (item) found.push(statusEvent(item)); } } }'; + f.write('src/index.js', `function collect(root) { ${shallow} ${deep} }`); + const base = f.commit(); + const args = [ + 'report', + '--kind', + 'eslint', + '--base', + base, + '--bootstrap', + '--owner', + 'quality-fixture', + '--expires', + '2099-12-31', + '--reason', + 'Historical lexical loop depth', + '--issue', + 'TEST-1', + '--', + process.execPath, + fileURLToPath( + new URL('../node_modules/eslint/bin/eslint.js', import.meta.url), + ), + '--config', + 'eslint.config.mjs', + '--no-inline-config', + '--format', + 'json', + 'src/index.js', + ]; + const original = f.run(...args); + assert.equal(original.status, 0, original.stderr); + const old = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.equal(old.entries.length, 1); + assert.equal(old.entries[0].value, 4); + f.write('src/index.js', `function collect(root) { ${deep} }`); + const reduced = f.run(...args); + assert.equal(reduced.status, 0, reduced.stderr); + const retained = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.equal(retained.entries[0].key, old.entries[0].key); + f.write( + 'src/index.js', + `function collect(root) { if (root.ready) { if (root.active) { ${shallow} } } }`, + ); + const transfer = f.run(...args); + assert.equal(transfer.status, 1, transfer.stderr); + assert.match(transfer.stderr, /Cannot baseline a new\/increased finding/); + f.write( + 'src/index.js', + `function collect(root) { if (root.ready) { ${deep} } }`, + ); + const growth = f.run(...args); + assert.equal(growth.status, 1, growth.stderr); + assert.match(growth.stderr, /Cannot baseline a new\/increased finding/); + } finally { + f.close(); + } +}); diff --git a/tools/quality/test/reports.test.mjs b/tools/quality/test/reports.test.mjs index 68c39e2..053a7df 100644 --- a/tools/quality/test/reports.test.mjs +++ b/tools/quality/test/reports.test.mjs @@ -190,3 +190,49 @@ test('invalid or missing scope evidence fails closed', () => { /Invalid syntax/, ); }); + +/** Equal statements under distinct lexical loop bindings are independently addressable even when only one is over threshold. */ +test('loop headers distinguish nesting and callback owners without body ordinals', async () => { + const source = `function collect(root) { + for (const ack of root.ack) { const item = record(ack); if (item) found.push(statusEvent(item)); } + for (const entry of root.entry) { for (const change of entry.changes) { + for (const status of change.statuses) { const item = record(status); if (item) found.push(statusEvent(item)); } + } } + }`; + const original = await findings(source, 'max-depth', 3); + assert.equal(original.length, 1); + assert.equal(original[0].value, 4); + assert.deepEqual( + await findings( + source.replace('const ack', '/* Header documentation */ const ack'), + 'max-depth', + 3, + ), + original, + ); + const callbacks = `for (const ack of root.ack) { run(${callback(2)}); } + for (const status of root.statuses) { run(${callback(2)}); } + for (const key in root.properties) { run(${callback(2)}); } + for (let index = 0; index < root.length; index++) { run(${callback(2)}); }`; + const owned = await findings(callbacks); + assert.equal(owned.length, 4); + assert.equal(new Set(owned.map(({ key }) => key)).size, 4); + const asynchronous = await findings( + `for await (const ack of root.ack) { run(${callback(2)}); }`, + ); + assert.equal(asynchronous.length, 1); + assert.ok(!owned.some(({ key }) => key === asynchronous[0].key)); + const shifted = await findings( + callbacks.replace('const ack of root.ack', 'const other of root.ack'), + ); + assert.equal( + shifted.filter(({ key }) => !owned.some((old) => old.key === key)).length, + 1, + ); +}); + +/** Repeated loops with identical headers remain ambiguous; distinct bindings must never enable ordinal-based allowance borrowing. */ +test('identical loop bindings do not disambiguate indistinguishable callbacks', async () => { + const loop = `for (const item of root.items) { run(${callback(2)}); }`; + await assert.rejects(() => findings(loop + loop), /Ambiguous lexical scope/); +}); From 8f07b83fe93a8cd1adf8698701b8948675ce283a Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 01:53:55 +0500 Subject: [PATCH 5/8] chore(quality): adopt sealed analyzer 1.0.10 --- tools/quality/README.md | 21 +++- tools/quality/lib/guards.mjs | 18 +++- tools/quality/lib/reports.mjs | 110 ++++++++++++++++++++- tools/quality/package-lock.json | 4 +- tools/quality/package.json | 2 +- tools/quality/template-manifest.json | 17 ++-- tools/quality/test/cli.test.mjs | 80 +++++++++++++++ tools/quality/test/guard-history.test.mjs | 113 ++++++++++++++++++++++ tools/quality/test/reports.test.mjs | 106 ++++++++++++++++++++ 9 files changed, 456 insertions(+), 15 deletions(-) create mode 100644 tools/quality/test/guard-history.test.mjs diff --git a/tools/quality/README.md b/tools/quality/README.md index aa67e5b..2e4def1 100644 --- a/tools/quality/README.md +++ b/tools/quality/README.md @@ -1,4 +1,4 @@ -# 1MSG quality template 1.0.9 +# 1MSG quality template 1.0.10 Vendored, private template for 1MSG-156. Install its exact tools with `npm --prefix tools/quality ci` on Node 24.19.0. The lockfile and @@ -118,3 +118,22 @@ ordinals do not identify allowances; indistinguishable sibling loops still fail closed. Consumers must replay their original trusted adoption base with the updated analyzer, preserving debt owners, deadlines and reasons. Do not translate baseline keys manually or renew historical debt as part of the version update. + +## 1.0.10 migration + +Otherwise identical sibling scopes use the nearest distinguishing parsed branch or +block context, including then/else, loop, switch and try/catch/finally roles. This +fallback leaves already unambiguous identities unchanged. The complete ordered +peer evidence remains part of an ambiguous group's identity; swaps, new peers, +growth and fully indistinguishable ancestry cannot borrow another allowance. +ESLint object-property diagnostics resolve the exact property name to its direct +callable initializer. Previously misattributed nested callback metrics now belong +to that callback, rather than its enclosing function. Consumers must replay their +original trusted adoption base; preserve owners, expiry and reasons and never +translate baseline keys manually. + +For function documentation only, a syntax error in trusted historical source +removes all inherited function signatures: every current function in that file +must have documentation. Current syntax errors and historical/current I/O, +configuration or Git failures remain fatal. This conservative documentation +fallback does not alter metric analysis, source coverage or debt baselines. diff --git a/tools/quality/lib/guards.mjs b/tools/quality/lib/guards.mjs index f27c583..69e3bde 100644 --- a/tools/quality/lib/guards.mjs +++ b/tools/quality/lib/guards.mjs @@ -211,12 +211,15 @@ function callbackComments(node, ast) { return comments; } +/** Identify source syntax failures without conflating analyzer, configuration or I/O errors. */ +class SourceParseError extends SyntaxError {} + /** Extract all implemented functions, including private methods, factories and substantive callbacks. */ export function functionsIn(path, text) { const functions = []; for (const { suffix, ast } of parseUnits(path, text)) { if (ast.parseDiagnostics.length) - throw new Error( + throw new SourceParseError( `Cannot parse ${path}: ${ast.parseDiagnostics[0].messageText}`, ); const visit = (node) => { @@ -266,6 +269,17 @@ export function functionsIn(path, text) { return functions; } +/** Invalid historical syntax earns no unchanged-function allowance; every current function must satisfy the documentation contract. */ +function historicalFunctions(path, text) { + if (text === null) return []; + try { + return functionsIn(path, text); + } catch (error) { + if (error instanceof SourceParseError) return []; + throw error; + } +} + /** Identify suppression directives in comments only, never in strings or generated documentation examples. */ export function suppressionErrors(path, text, config) { const errors = []; @@ -358,7 +372,7 @@ export function runGuards(config, base) { continue; const before = baseFile(base, path); const previous = new Map(); - for (const fn of before === null ? [] : functionsIn(path, before)) { + for (const fn of historicalFunctions(path, before)) { const identity = `${fn.key}:${fn.signature}`; previous.set(identity, (previous.get(identity) ?? 0) + 1); } diff --git a/tools/quality/lib/reports.mjs b/tools/quality/lib/reports.mjs index b70336f..4cec53b 100644 --- a/tools/quality/lib/reports.mjs +++ b/tools/quality/lib/reports.mjs @@ -329,6 +329,92 @@ function isDepthScope(node) { ].includes(node.kind); } +/** Identify a control-flow child by its semantic role, never its position among statements. */ +function branchRole(parent, child) { + if (ts.isIfStatement(parent) || ts.isConditionalExpression(parent)) { + if (child === (parent.thenStatement ?? parent.whenTrue)) return 'then'; + if (child === (parent.elseStatement ?? parent.whenFalse)) return 'else'; + return 'condition'; + } + if (ts.isTryStatement(parent)) { + if (child === parent.tryBlock) return 'try'; + if (child === parent.catchClause) return 'catch'; + return 'finally'; + } + if (ts.isCatchClause(parent)) + return child === parent.block ? 'body' : 'binding'; + if (ts.isCaseClause(parent)) + return child === parent.expression ? 'case-value' : 'case-body'; + if (ts.isDefaultClause(parent)) return 'default-body'; + if (ts.isSwitchStatement(parent)) + return child === parent.caseBlock ? 'cases' : 'expression'; + if (isDepthScope(parent)) + return child === parent.statement ? 'body' : 'header'; + return 'block'; +} + +/** Collect parsed enclosing branches only for otherwise indistinguishable peers; literal values and then/else roles remain evidence. */ +function structuralContext(node, source) { + const contexts = []; + let child = node; + for ( + let parent = node.parent; + parent && !ts.isSourceFile(parent); + parent = parent.parent + ) { + if ( + ts.isBlock(parent) || + isDepthScope(parent) || + ts.isConditionalExpression(parent) || + ts.isCatchClause(parent) || + ts.isCaseClause(parent) || + ts.isDefaultClause(parent) + ) { + contexts.push([ + ts.SyntaxKind[parent.kind], + branchRole(parent, child), + syntaxFingerprint(parent, source), + ]); + } + child = parent; + } + return contexts; +} + +/** Find the shortest unique ancestor prefix among equal bodies; completely equal ancestry still has no safe correspondence. */ +function distinctContexts(nodes, fingerprints, source) { + const contexts = nodes.map( + /** Avoid introducing contextual identities for a body already distinguished by its own syntax. */ + (node, index) => + fingerprints.indexOf(fingerprints[index]) === + fingerprints.lastIndexOf(fingerprints[index]) + ? [] + : structuralContext(node, source), + ); + return contexts.map( + /** Select the shortest semantic ancestor evidence that separates this body from its equal peers. */ ( + context, + index, + ) => { + const peers = fingerprints.flatMap((fingerprint, peer) => + fingerprint === fingerprints[index] && peer !== index ? [peer] : [], + ); + if (!peers.length) return null; + for (let length = 1; length <= context.length; length++) { + const candidate = JSON.stringify(context.slice(0, length)); + if ( + peers.every( + (peer) => + JSON.stringify(contexts[peer].slice(0, length)) !== candidate, + ) + ) + return candidate; + } + return null; + }, + ); +} + /** Index all lexical scopes, including functions below lint thresholds, so disappearing diagnostics cannot renumber another allowance. */ function scopeIdentities(source, depth = false) { const groups = new Map(); @@ -360,6 +446,15 @@ function scopeIdentities(source, depth = false) { const fingerprints = nodes.map((node) => syntaxFingerprint(node, source)); // Preserve source order in ambiguous groups: swapping a large and small body must not transfer the large allowance. const group = digest(JSON.stringify(fingerprints)); + const contexts = distinctContexts(nodes, fingerprints, source); + const contextualGroup = digest( + JSON.stringify( + fingerprints.map((fingerprint, index) => [ + fingerprint, + contexts[index], + ]), + ), + ); for (const [index, node] of nodes.entries()) { const fingerprint = fingerprints[index]; // A changed ambiguous group loses every old allowance; even matching another old body cannot borrow its budget. @@ -368,7 +463,9 @@ function scopeIdentities(source, depth = false) { fingerprints.indexOf(fingerprint) === fingerprints.lastIndexOf(fingerprint) ? `${owner}|group:${group}|member:${fingerprint}` - : null, + : contexts[index] === null + ? null + : `${owner}|context-group:${contextualGroup}|member:${fingerprint}|context:${digest(contexts[index])}`, ); } } @@ -386,6 +483,17 @@ function scopeAt(source, identities, line, column) { function visit(node) { if (node.getStart(source) <= offset && node.end > offset) { if (identities.has(node)) matched = node; + // ESLint complexity locates a named object property before its arrow/function initializer. + // Resolve only that direct callable initializer, never an unrelated neighboring function. + if ( + ts.isPropertyAssignment(node) && + ts.isFunctionLike(node.initializer) && + identities.has(node.initializer) && + offset >= node.name.getStart(source) && + offset < node.name.end + ) { + matched = node.initializer; + } ts.forEachChild(node, visit); } } diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json index 0c6a588..5e6bab1 100644 --- a/tools/quality/package-lock.json +++ b/tools/quality/package-lock.json @@ -1,12 +1,12 @@ { "name": "@1msg/quality-template", - "version": "1.0.9", + "version": "1.0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@1msg/quality-template", - "version": "1.0.9", + "version": "1.0.10", "dependencies": { "@eslint/js": "9.39.5", "dependency-cruiser": "18.6.0", diff --git a/tools/quality/package.json b/tools/quality/package.json index 0620fb9..07e7cfe 100644 --- a/tools/quality/package.json +++ b/tools/quality/package.json @@ -1,6 +1,6 @@ { "name": "@1msg/quality-template", - "version": "1.0.9", + "version": "1.0.10", "private": true, "type": "module", "engines": { diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json index 883a990..f2cf559 100644 --- a/tools/quality/template-manifest.json +++ b/tools/quality/template-manifest.json @@ -1,27 +1,28 @@ { "schemaVersion": 1, - "version": "1.0.9", + "version": "1.0.10", "files": { - "README.md": "91dd028828d08424d26dd4f5fc1e91da5c2258a3604a2fab57658c0f1c59b745", + "README.md": "50df5c60db609380718c9228de8f8f53cf1949673bd66f71a9f0192fae1d6dbd", "canonical-duplicates.mjs": "a3583fdc3e344af448ea8d2543c2398daaa03fa10a0739da486afb04e35425ba", "complexity.mjs": "4ed5553c392621e0615a48c12e12300c8602ed2a28cfbaff67002acf82e49cac", "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", "lib/baseline.mjs": "7876ba90b80448d9c9003c21e348095ed22630c41fc26ed944984742020549dd", "lib/git.mjs": "b7c26871526d864bf8d12f01c613d3bfa0adb2da9d072544d8f09407ef598758", - "lib/guards.mjs": "e94dc6b58703b44420f8b815ee069b9e0a7fa9aefd5faba63d55f1c3da7c4286", + "lib/guards.mjs": "b1b025a1fdcb63434733216a4faaa45112aa404f26f9d31df28921243d6a22f8", "lib/historical.mjs": "43b46395828daa3f19d8692e9bd22ea6cfc1d0dbac83814d727894f672a0ddd2", "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", - "lib/reports.mjs": "e41c4994e444128ae0418eff7240f49de678a97112fa7d5171fbe680d26b6dff", + "lib/reports.mjs": "361e38ae981238db91f7b9a31af963ccbb89e3ae6745d1582b2086e6c64f0c9e", "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", - "package-lock.json": "314de2cb801a00bb42240da3567274bac9725359c0429665c505653a51bf5f91", - "package.json": "e1228b0144b1d8bd79283bfacec0be9a54f636e973ba42de4b1cc3694972f57e", + "package-lock.json": "85c154a1d50a55d975a56f173a25eb5be3ef6ae7ffa111726531e31246621907", + "package.json": "188e7badefdaa40018946b7d320f8c87385ba146ead7e404b3abc5ec371eb249", "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", "run.mjs": "7cf26128cdf63f3a7ccab7341a0a274a352fd9bda0521ba41e37216bb9cc249f", "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", - "test/cli.test.mjs": "63350dcf9c58c0e41d0dcc49bb8b9eef8dd0c01e781f25a58490f1476f58e94a", + "test/cli.test.mjs": "bd3445143a45aabba2a95593aace73f96223389f7a440c2ef41bf639bb4ec12a", "test/complexity.test.mjs": "ba1f702ba94de3fcad93cb5e43a49bc2456be1426c81754149420d210f2b3952", + "test/guard-history.test.mjs": "b699cc394b9c843a59798f28fe2b5dd6c199c3f3e16dc1c61c35724a935fc23e", "test/ratchet.test.mjs": "324a932c5a52d1b037e111042e1b41e5686f8d4dbfd0307faf86cee649ebc27a", - "test/reports.test.mjs": "3d5be0312d4870dd00e4cdafaa422d1e0d4e0d3ecaf4dc65a73a4dac577bfbfa", + "test/reports.test.mjs": "521a13da2f16628b4a30de7040529e0b7b7e25e7db79d19de8004945d49c5e0c", "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", "tsconfig.node.json": "627661abcb7e992c4bfaf98d6e68a12678573b5d4f6e821ea0fa43fa6e233f28", "tsconfig.svelte.json": "5777247ea98aaf2d886b87cd12206a641377edcdd086ce5fd5b58adc6f0bc771" diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs index 33425a7..92c7b32 100644 --- a/tools/quality/test/cli.test.mjs +++ b/tools/quality/test/cli.test.mjs @@ -823,3 +823,83 @@ test('actual raw complexity CLI distinguishes lexical loops and rejects depth tr f.close(); } }); + +/** Raw historical replay resolves Core-shaped duplicate try blocks while rejecting swaps, added scopes and increased nesting. */ +test('actual complexity CLI validates structural context without transferring debt', () => { + const f = fixture(); + try { + f.write( + 'eslint.config.mjs', + "export default [{rules:{'max-depth':['error',3]}}];", + ); + const text = + 'if (match) { if (template.rejected) { try { send(template); } catch (error) { record(error); } } else { saveText(template); } }'; + const document = text.replace('saveText', 'saveDocument'); + /** Retain branch code while varying only a surrounding while depth or branch sequence. */ + const source = (loops, branches) => + `function collect(root) { ${'while (root.ready) {'.repeat(loops)} if (root.templates) { for (const template of root.templates) { ${branches.join('\n')} } } ${'}'.repeat(loops)} }`; + f.write('src/index.js', source(2, [text, document])); + const base = f.commit(); + const args = [ + 'report', + '--kind', + 'eslint', + '--base', + base, + '--bootstrap', + '--owner', + 'quality-fixture', + '--expires', + '2099-12-31', + '--reason', + 'Historical structural branch depth', + '--issue', + 'TEST-1', + '--', + process.execPath, + fileURLToPath( + new URL('../node_modules/eslint/bin/eslint.js', import.meta.url), + ), + '--config', + 'eslint.config.mjs', + '--no-inline-config', + '--format', + 'json', + 'src/index.js', + ]; + const original = f.run(...args); + assert.equal(original.status, 0, original.stderr); + const old = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.ok(old.entries.some(({ key }) => key.includes('context-group:'))); + f.write('src/index.js', source(1, [text, document])); + const reduced = f.run(...args); + assert.equal(reduced.status, 0, reduced.stderr); + const retained = JSON.parse( + readFileSync(join(f.cwd, 'quality/baselines/complexity.json'), 'utf8'), + ); + assert.ok( + retained.entries.every((entry) => + old.entries.some( + (prior) => prior.key === entry.key && prior.value >= entry.value, + ), + ), + ); + for (const current of [ + source(2, [document, text]), + source(2, [text, document, text.replace('saveText', 'saveImage')]), + source(3, [text, document]), + ]) { + f.write('src/index.js', current); + const violation = f.run(...args); + assert.equal(violation.status, 1, violation.stderr); + assert.match( + violation.stderr, + /Cannot baseline a new\/increased finding/, + ); + } + } finally { + f.close(); + } +}); diff --git a/tools/quality/test/guard-history.test.mjs b/tools/quality/test/guard-history.test.mjs new file mode 100644 index 0000000..b49ffa7 --- /dev/null +++ b/tools/quality/test/guard-history.test.mjs @@ -0,0 +1,113 @@ +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import test from 'node:test'; +import { fileURLToPath } from 'node:url'; + +const runner = fileURLToPath(new URL('../run.mjs', import.meta.url)); + +/** Build independent Git history so the actual CLI must distinguish trusted historical syntax from current source failures. */ +function fixture() { + const cwd = mkdtempSync(join(tmpdir(), 'quality-guard-history-')); + const env = { ...process.env, CI: '', QUALITY_BASE: undefined }; + for (const name of Object.keys(env)) { + if (name.startsWith('GIT_')) delete env[name]; + } + env.GIT_CONFIG_GLOBAL = process.platform === 'win32' ? 'NUL' : '/dev/null'; + env.GIT_CONFIG_NOSYSTEM = '1'; + mkdirSync(join(cwd, 'src')); + writeFileSync( + join(cwd, 'quality.config.mjs'), + "export default {schemaVersion:1,profile:'B',defaultBranch:'main',sourceRoots:['src','quality.config.mjs']};\n", + ); + const git = (...args) => { + const result = spawnSync('git', args, { cwd, env, encoding: 'utf8' }); + assert.equal(result.status, 0, result.stderr); + return result.stdout.trim(); + }; + git('init', '-b', 'main'); + git('config', 'user.name', 'Quality fixture'); + git('config', 'user.email', 'quality@example.invalid'); + return { + cwd, + write: (text) => writeFileSync(join(cwd, 'src/Widget.svelte'), text), + commit: () => { + git('add', '.'); + git('commit', '-m', 'test: historical syntax'); + return git('rev-parse', 'HEAD'); + }, + run: (base) => + spawnSync(process.execPath, [runner, 'guards', '--base', base], { + cwd, + env, + encoding: 'utf8', + timeout: 30_000, + }), + close: () => rmSync(cwd, { recursive: true, force: true }), + }; +} + +test('actual guards require all current docs after unparseable trusted Svelte history', () => { + const f = fixture(); + try { + // Historical markup embeds script text in a JavaScript template; the old script extractor cannot parse that extra unit. + f.write( + '\n', + ); + const base = f.commit(); + f.write( + '\n

Readable widget

', + ); + const undocumented = f.run(base); + assert.notEqual(undocumented.status, 0); + assert.match(undocumented.stderr, /document stable/); + assert.match(undocumented.stderr, /document changed/); + assert.doesNotMatch(undocumented.stderr, /Cannot parse/); + + f.write( + '\n

Readable widget

', + ); + const documented = f.run(base); + assert.equal(documented.status, 0, documented.stderr); + assert.match(documented.stdout, /guards: PASS/); + + f.write(''); + const invalidCurrent = f.run(base); + assert.notEqual(invalidCurrent.status, 0); + assert.match(invalidCurrent.stderr, /Cannot parse src\/Widget\.svelte/); + + const invalidBase = f.run('nonexistent-trusted-reference'); + assert.notEqual(invalidBase.status, 0); + assert.match(invalidBase.stderr, /git rev-parse failed/); + } finally { + f.close(); + } +}); + +test('historical fallback does not consume source I/O or configuration failures', () => { + const f = fixture(); + try { + f.write(''); + const base = f.commit(); + rmSync(join(f.cwd, 'src/Widget.svelte')); + mkdirSync(join(f.cwd, 'src/Widget.svelte')); + const invalidInput = f.run(base); + assert.notEqual(invalidInput.status, 0); + assert.match( + invalidInput.stderr, + /EISDIR|illegal operation on a directory/, + ); + + writeFileSync( + join(f.cwd, 'quality.config.mjs'), + 'export default {schemaVersion:1,profile:"unknown",sourceRoots:["src"]};', + ); + const invalidConfig = f.run(base); + assert.notEqual(invalidConfig.status, 0); + assert.match(invalidConfig.stderr, /concrete profile/); + } finally { + f.close(); + } +}); diff --git a/tools/quality/test/reports.test.mjs b/tools/quality/test/reports.test.mjs index 053a7df..339ee55 100644 --- a/tools/quality/test/reports.test.mjs +++ b/tools/quality/test/reports.test.mjs @@ -236,3 +236,109 @@ test('identical loop bindings do not disambiguate indistinguishable callbacks', const loop = `for (const item of root.items) { run(${callback(2)}); }`; await assert.rejects(() => findings(loop + loop), /Ambiguous lexical scope/); }); + +/** Equal try blocks in text/document template branches need their differing surrounding branch bodies as evidence. */ +test('identical scopes use the nearest distinguishing structural branch context', async () => { + const source = `function templates(root) { + while (root.ready) { if (root.templates) { for (const template of root.templates) { + if (match) { if (template.rejected) { try { send(template); } catch (error) { record(error); } } else { saveText(template); } } + if (match) { if (template.rejected) { try { send(template); } catch (error) { record(error); } } else { saveDocument(template); } } + } } } + }`; + const records = await findings(source, 'max-depth', 3); + assert.ok(records.some(({ key }) => key.includes('context-group:'))); + assert.equal(new Set(records.map(({ key }) => key)).size, records.length); + const callbacks = `if (ready) { run(${callback(2)}); } else { run(${callback(2)}); } + try { run(${callback(2)}); } catch (error) { run(${callback(2)}); } finally { run(${callback(2)}); } + switch (kind) { case 'first': run(${callback(2)}); break; case 'second': run(${callback(2)}); break; default: run(${callback(2)}); } + while (active) { run(${callback(2)}); } + do { run(${callback(2)}); } while (active);`; + const owned = await findings(callbacks); + assert.equal(owned.length, 10); + assert.equal(new Set(owned.map(({ key }) => key)).size, 10); + assert.deepEqual( + await findings( + callbacks.replaceAll('run(', '/* Branch documentation */ run('), + ), + owned, + ); +}); + +/** Identical branches and predicates provide no trustworthy address merely because they appear at different source offsets. */ +test('identical structural ancestry still fails closed', async () => { + const branch = `if (ready) { run(${callback(2)}); }`; + await assert.rejects( + () => findings(branch + branch), + /Ambiguous lexical scope/, + ); +}); + +/** ESLint names object-property callbacks at the property token, which precedes the actual function start. */ +test('object property diagnostics resolve only their direct callable initializer', async () => { + for (const fn of [ + `async ${callback(2)}`, + 'async function(value) { if (value.p0) return 1; if (value.p1) return 2; return 0; }', + ]) { + const source = `const endpoints = { handler: ${fn}, unrelated: 1 };`; + const report = await analyze(source); + assert.equal(report[0].messages[0].column, source.indexOf('handler') + 1); + const records = eslintRecords(report); + assert.equal(records.length, 1); + assert.match(records[0].key, /handler/); + assert.deepEqual( + await findings(source.replace('handler:', 'handler: /* Contract */')), + records, + ); + for (const column of [ + source.indexOf('handler:') + 'handler'.length + 1, + source.indexOf('unrelated') + 1, + ]) { + assert.throws( + () => + eslintRecords([ + { + filePath: 'invalid-location.js', + source, + messages: [ + { + ruleId: 'complexity', + line: 1, + column, + message: 'Function has a complexity of 4.', + }, + ], + }, + ]), + /No lexical scope/, + ); + } + } + assert.throws( + () => + eslintRecords([ + { + filePath: 'invalid-location.js', + source: 'const settings = { threshold: 5 };', + messages: [ + { + ruleId: 'complexity', + line: 1, + column: 20, + message: 'Function has a complexity of 4.', + }, + ], + }, + ]), + /No lexical scope/, + ); +}); + +/** An object callback diagnostic inside another function must not consume that enclosing function's complexity allowance. */ +test('object callbacks retain their own budget inside enclosing functions', async () => { + const source = `function useCheckout() { return useMutation({ onError: ${callback(2)} }); }`; + const report = await analyze(source); + assert.equal(report[0].messages.length, 1); + const record = eslintRecords(report)[0]; + assert.match(record.scope, /PropertyAssignment.*onError.*ArrowFunction/); + assert.equal(record.value, 3); +}); From 59da085d3cfae658113655c388cd22aebad569b6 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 02:57:38 +0500 Subject: [PATCH 6/8] fix(quality): support older Git in shared fixtures --- tools/quality/README.md | 15 ++- tools/quality/package-lock.json | 4 +- tools/quality/package.json | 2 +- tools/quality/template-manifest.json | 13 +-- tools/quality/test/cli.test.mjs | 3 +- tools/quality/test/git-portability.test.mjs | 100 ++++++++++++++++++++ tools/quality/test/guard-history.test.mjs | 3 +- 7 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 tools/quality/test/git-portability.test.mjs diff --git a/tools/quality/README.md b/tools/quality/README.md index 2e4def1..9c78337 100644 --- a/tools/quality/README.md +++ b/tools/quality/README.md @@ -1,4 +1,4 @@ -# 1MSG quality template 1.0.10 +# 1MSG quality template 1.0.11 Vendored, private template for 1MSG-156. Install its exact tools with `npm --prefix tools/quality ci` on Node 24.19.0. The lockfile and @@ -137,3 +137,16 @@ removes all inherited function signatures: every current function in that file must have documentation. Current syntax errors and historical/current I/O, configuration or Git failures remain fatal. This conservative documentation fallback does not alter metric analysis, source coverage or debt baselines. + +## 1.0.11 migration + +Test repositories now initialize their default branch with `git init` followed by +`git symbolic-ref HEAD refs/heads/main`. This works on the older Git installation +used by the self-hosted runner, which does not support `git init -b`. A regression +fixture rejects that unsupported option and replays both actual Git-backed test +families through a subprocess-only Node preload shim; all other Git operations +remain real. The fixture uses no Unix executable or shebang assumptions and does +not modify the runtime Git driver or skip checks on Windows. +Only fixture setup changes: analysis rules, historical identities and baseline +records are unchanged. Copy the complete sealed version without changing debt +owners, reasons, issue links, expiry dates or baseline entries. diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json index 5e6bab1..527d33a 100644 --- a/tools/quality/package-lock.json +++ b/tools/quality/package-lock.json @@ -1,12 +1,12 @@ { "name": "@1msg/quality-template", - "version": "1.0.10", + "version": "1.0.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@1msg/quality-template", - "version": "1.0.10", + "version": "1.0.11", "dependencies": { "@eslint/js": "9.39.5", "dependency-cruiser": "18.6.0", diff --git a/tools/quality/package.json b/tools/quality/package.json index 07e7cfe..67942c0 100644 --- a/tools/quality/package.json +++ b/tools/quality/package.json @@ -1,6 +1,6 @@ { "name": "@1msg/quality-template", - "version": "1.0.10", + "version": "1.0.11", "private": true, "type": "module", "engines": { diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json index f2cf559..210f229 100644 --- a/tools/quality/template-manifest.json +++ b/tools/quality/template-manifest.json @@ -1,8 +1,8 @@ { "schemaVersion": 1, - "version": "1.0.10", + "version": "1.0.11", "files": { - "README.md": "50df5c60db609380718c9228de8f8f53cf1949673bd66f71a9f0192fae1d6dbd", + "README.md": "6760e252841ba82078ede1589a474dd19c8f77f828245e181f34e842465c3aa1", "canonical-duplicates.mjs": "a3583fdc3e344af448ea8d2543c2398daaa03fa10a0739da486afb04e35425ba", "complexity.mjs": "4ed5553c392621e0615a48c12e12300c8602ed2a28cfbaff67002acf82e49cac", "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", @@ -13,14 +13,15 @@ "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", "lib/reports.mjs": "361e38ae981238db91f7b9a31af963ccbb89e3ae6745d1582b2086e6c64f0c9e", "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", - "package-lock.json": "85c154a1d50a55d975a56f173a25eb5be3ef6ae7ffa111726531e31246621907", - "package.json": "188e7badefdaa40018946b7d320f8c87385ba146ead7e404b3abc5ec371eb249", + "package-lock.json": "9fc7d279d2bade1c42f807d99a107d77f15a8e42edd2a9b32b4b5ce1a4fda35f", + "package.json": "deb5fd5e972aec2926b21e31d02c47e9c35d507048e83ab0ed161425151546e2", "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", "run.mjs": "7cf26128cdf63f3a7ccab7341a0a274a352fd9bda0521ba41e37216bb9cc249f", "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", - "test/cli.test.mjs": "bd3445143a45aabba2a95593aace73f96223389f7a440c2ef41bf639bb4ec12a", + "test/cli.test.mjs": "49c55b1b4cf2ca2214b0f1b5d2bd973eac43005e14606f27a2a4aa682e0e691d", "test/complexity.test.mjs": "ba1f702ba94de3fcad93cb5e43a49bc2456be1426c81754149420d210f2b3952", - "test/guard-history.test.mjs": "b699cc394b9c843a59798f28fe2b5dd6c199c3f3e16dc1c61c35724a935fc23e", + "test/git-portability.test.mjs": "0e65759ff3a1aa87c20d20ae147154d980381c2e8075f57f341ef3c53c3b3f62", + "test/guard-history.test.mjs": "00b17403b3ef17cc5d83c681c990ca98b6a0ad4857a95d501d2cf8f390aa7b1e", "test/ratchet.test.mjs": "324a932c5a52d1b037e111042e1b41e5686f8d4dbfd0307faf86cee649ebc27a", "test/reports.test.mjs": "521a13da2f16628b4a30de7040529e0b7b7e25e7db79d19de8004945d49c5e0c", "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs index 92c7b32..0c8d1cd 100644 --- a/tools/quality/test/cli.test.mjs +++ b/tools/quality/test/cli.test.mjs @@ -40,7 +40,8 @@ function fixture() { assert.equal(result.status, 0, result.stderr); return result.stdout.trim(); }; - git('init', '-b', 'main'); + git('init'); + git('symbolic-ref', 'HEAD', 'refs/heads/main'); git('config', 'user.email', 'quality@example.invalid'); git('config', 'user.name', 'Quality fixture'); const commit = () => { diff --git a/tools/quality/test/git-portability.test.mjs b/tools/quality/test/git-portability.test.mjs new file mode 100644 index 0000000..832c379 --- /dev/null +++ b/tools/quality/test/git-portability.test.mjs @@ -0,0 +1,100 @@ +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import test from 'node:test'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +/** Re-run both real Git fixture families under an old-Git command boundary; no successful Git operation is substituted. */ +test('Git fixtures retain real history when git init does not support branch flags', () => { + const cwd = mkdtempSync(join(tmpdir(), 'quality-old-git-')); + const log = join(cwd, 'git-calls.jsonl'); + const shim = join(cwd, 'reject-new-git-flags.mjs'); + // A Node preload avoids Unix executable/shebang assumptions and affects only this test's child processes. + writeFileSync( + shim, + ` +import childProcess from 'node:child_process'; +import { appendFileSync } from 'node:fs'; +import { syncBuiltinESMExports } from 'node:module'; +const actualSpawnSync = childProcess.spawnSync; +childProcess.spawnSync = function(command, args = [], options) { + if (command === 'git') { + appendFileSync(process.env.QUALITY_PORTABILITY_LOG, JSON.stringify(args) + '\\n'); + if (args[0] === 'init' && args.some((arg) => arg.startsWith('-b') || arg === '--initial-branch' || arg.startsWith('--initial-branch='))) { + return actualSpawnSync(process.execPath, ['-e', 'process.stderr.write("fixture: git init branch flags are unavailable\\\\n"); process.exit(97)'], options); + } + } + return actualSpawnSync(command, args, options); +}; +syncBuiltinESMExports(); +`, + ); + const env = { + ...process.env, + NODE_OPTIONS: `${process.env.NODE_OPTIONS ?? ''} --import=${pathToFileURL(shim).href}`, + QUALITY_PORTABILITY_LOG: log, + }; + // This is an independent runner, not a child shard controlled by the outer Node test harness. + delete env.NODE_TEST_CONTEXT; + try { + // Prove the child-process boundary actually rejects the formerly required invocation. + const unsupported = spawnSync( + process.execPath, + [ + '--input-type=module', + '-e', + ` + import { spawnSync } from 'node:child_process'; + const result = spawnSync('git', ['init', '-b', 'main'], {encoding:'utf8'}); + process.stderr.write(result.stderr ?? ''); + process.exit(result.status ?? 1); + `, + ], + { cwd, env, encoding: 'utf8' }, + ); + assert.equal(unsupported.status, 97, unsupported.stderr); + assert.match(unsupported.stderr, /branch flags are unavailable/); + const template = fileURLToPath(new URL('..', import.meta.url)); + const result = spawnSync( + process.execPath, + [ + '--test', + '--test-reporter=tap', + '--test-name-pattern=real CLI blocks undocumented|actual guards require all current docs', + join(template, 'test/cli.test.mjs'), + join(template, 'test/guard-history.test.mjs'), + ], + { + cwd: template, + env, + encoding: 'utf8', + timeout: 60_000, + maxBuffer: 8 * 1024 * 1024, + }, + ); + assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`); + assert.match(result.stdout, /# pass 2\b/); + assert.match(result.stdout, /# fail 0\b/); + const calls = readFileSync(log, 'utf8') + .trim() + .split('\n') + .map((line) => JSON.parse(line)); + assert.equal( + calls.filter((args) => JSON.stringify(args) === '["init"]').length, + 2, + ); + assert.equal( + calls.filter( + (args) => + JSON.stringify(args) === '["symbolic-ref","HEAD","refs/heads/main"]', + ).length, + 2, + ); + assert.ok(calls.some((args) => args[0] === 'commit')); + assert.ok(calls.some((args) => args[0] === 'show')); + } finally { + rmSync(cwd, { recursive: true, force: true }); + } +}); diff --git a/tools/quality/test/guard-history.test.mjs b/tools/quality/test/guard-history.test.mjs index b49ffa7..390086e 100644 --- a/tools/quality/test/guard-history.test.mjs +++ b/tools/quality/test/guard-history.test.mjs @@ -27,7 +27,8 @@ function fixture() { assert.equal(result.status, 0, result.stderr); return result.stdout.trim(); }; - git('init', '-b', 'main'); + git('init'); + git('symbolic-ref', 'HEAD', 'refs/heads/main'); git('config', 'user.name', 'Quality fixture'); git('config', 'user.email', 'quality@example.invalid'); return { From 0ff37cbc533d291e4fefb46575659e35ea129c03 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 08:40:10 +0500 Subject: [PATCH 7/8] chore(quality): check authored extensions and reject unprogrammed TypeScript --- .github/workflows/quality.yml | 2 +- eslint.config.mjs | 4 + knip.json | 8 +- package.json | 17 ++- quality.config.mjs | 2 +- quality/hooks.test.mjs | 207 ++++++++++++++++++++++++++++++++++ quality/typescript-policy.mjs | 24 ++++ 7 files changed, 254 insertions(+), 10 deletions(-) create mode 100644 quality/hooks.test.mjs create mode 100644 quality/typescript-policy.mjs diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 740beeb..68a46d2 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -24,7 +24,7 @@ jobs: java-version: "24" - run: npm ci - run: npm --prefix tools/quality ci - - run: node --test tools/quality/test/*.test.mjs + - run: npm run test:quality - run: node tools/quality/run.mjs guards - run: npm run format:check - run: npm run lint:static diff --git a/eslint.config.mjs b/eslint.config.mjs index b3efe8c..808bb4b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,5 +1,9 @@ import { staticConfig, globals } from "./tools/quality/eslint.mjs"; export default [ + { + files: ["**/*.jsx"], + languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } }, + }, { ignores: [ "**/node_modules/**", diff --git a/knip.json b/knip.json index 97f2c38..b889c5b 100644 --- a/knip.json +++ b/knip.json @@ -1,12 +1,14 @@ { "entry": [ "quality/generator/generate.mjs!", - "quality/generator/verify-negative.mjs!", + "quality/generator/verify-negative.mjs", "quality/postprocess.mjs!", "eslint.config.mjs", - "quality.config.mjs" + "quality.config.mjs", + "quality/hooks.test.mjs", + "quality/typescript-policy.mjs" ], - "project": ["quality/**/*.mjs!", "*.mjs"], + "project": ["quality/**/*.{js,jsx,mjs,cjs}!", "*.{js,jsx,mjs,cjs}"], "ignoreBinaries": ["java"], "ignore": ["tools/quality/**"] } diff --git a/package.json b/package.json index 6d9b9b5..7c32aa2 100644 --- a/package.json +++ b/package.json @@ -8,18 +8,25 @@ }, "packageManager": "npm@11.17.0", "scripts": { - "format:check": "node tools/quality/node_modules/prettier/bin/prettier.cjs --check \"quality/**/*.mjs\" \"*.mjs\" package.json knip.json .github/workflows/quality.yml AGENTS.md", - "format": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write \"quality/**/*.mjs\" \"*.mjs\" package.json knip.json .github/workflows/quality.yml AGENTS.md", - "lint:static": "node tools/quality/node_modules/eslint/bin/eslint.js . --max-warnings=0", + "format:check": "node tools/quality/node_modules/prettier/bin/prettier.cjs --check \"quality/**/*.{js,jsx,mjs,cjs}\" \"*.{js,jsx,mjs,cjs}\" package.json knip.json .github/workflows/quality.yml AGENTS.md", + "format": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write \"quality/**/*.{js,jsx,mjs,cjs}\" \"*.{js,jsx,mjs,cjs}\" package.json knip.json .github/workflows/quality.yml AGENTS.md", + "lint:static": "node quality/typescript-policy.mjs && node tools/quality/node_modules/eslint/bin/eslint.js . --max-warnings=0", "quality:guards": "node tools/quality/run.mjs guards", "lint:unused:production": "node tools/quality/run.mjs unused-production", "lint:unused:full": "node tools/quality/run.mjs unused-full", "lint:duplicates": "node tools/quality/run.mjs duplicates", "lint:duplicates:full": "node tools/quality/run.mjs duplicates-full", - "test:quality": "node --test tools/quality/test/*.test.mjs", + "test:quality": "node --test tools/quality/test/*.test.mjs quality/hooks.test.mjs", "hooks:install": "node tools/quality/node_modules/husky/bin.js" }, "lint-staged": { - "*.{mjs,json,md,yml}": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write" + "*.{js,jsx,mjs,cjs}": [ + "node tools/quality/node_modules/prettier/bin/prettier.cjs --write", + "node tools/quality/node_modules/eslint/bin/eslint.js --config eslint.config.mjs --max-warnings=0" + ], + "*.{ts,tsx,mts,cts}": [ + "node quality/typescript-policy.mjs" + ], + "*.{json,md,yml,yaml}": "node tools/quality/node_modules/prettier/bin/prettier.cjs --write" } } diff --git a/quality.config.mjs b/quality.config.mjs index ed8ca14..e12ec8a 100644 --- a/quality.config.mjs +++ b/quality.config.mjs @@ -5,7 +5,7 @@ export default { sourceRoots: ["quality", "eslint.config.mjs", "quality.config.mjs"], generated: [], comments: { - full: ["quality/**/*.mjs"], + full: ["quality/**/*.{js,jsx,mjs,cjs}"], }, duplicatePaths: ["quality"], duplicateMaxPercentage: 0, diff --git a/quality/hooks.test.mjs b/quality/hooks.test.mjs new file mode 100644 index 0000000..8ef4fea --- /dev/null +++ b/quality/hooks.test.mjs @@ -0,0 +1,207 @@ +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { + chmodSync, + statSync, + copyFileSync, + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + symlinkSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import test from "node:test"; + +const repository = resolve("."); +const configuration = { + source: "quality", + tooling: "quality", + typed: false, + files: [ + "package.json", + "quality/typescript-policy.mjs", + ".husky/pre-commit", + "eslint.config.mjs", + "eslint.static.config.mjs", + "eslint.typed.config.mjs", + "eslint.hook.config.mjs", + "tsconfig.json", + "tsconfig.quality.json", + "prettier.config.mjs", + ".prettierrc", + ".prettierrc.json", + ".prettierrc.js", + ".prettierignore", + ], + links: ["tools/quality"], +}; + +/** Run the real hook tools with an isolated Git identity and bounded child lifetime. */ +function command(root, program, args) { + const env = { + ...process.env, + HUSKY: "1", + GIT_CONFIG_NOSYSTEM: "1", + GIT_CONFIG_GLOBAL: process.platform === "win32" ? "NUL" : "/dev/null", + }; + for (const key of Object.keys(env)) + if ( + key.startsWith("GIT_") && + !["GIT_CONFIG_NOSYSTEM", "GIT_CONFIG_GLOBAL"].includes(key) + ) + delete env[key]; + const result = spawnSync(program, args, { + cwd: root, + env, + encoding: "utf8", + timeout: 60_000, + maxBuffer: 8 * 1024 * 1024, + }); + assert.equal( + result.signal, + null, + `Fixture must finish by diagnostics: ${result.error ?? result.stderr}`, + ); + return result; +} + +/** Preserve full diagnostics when setup or a corrected commit unexpectedly fails. */ +function successful(root, program, args) { + const result = command(root, program, args); + assert.equal( + result.status, + 0, + `${program} ${args.join(" ")}\n${result.stdout}\n${result.stderr}`, + ); + return result.stdout.trim(); +} + +/** Copy production configuration and install the actual executable hook without borrowing the user's Git settings. */ +function fixture(t) { + const root = mkdtempSync(join(tmpdir(), "1msg-hook-extensions-")); + /** Remove only this disposable checkout after all real commit attempts finish. */ + t.after(() => rmSync(root, { recursive: true, force: true })); + for (const file of configuration.files) { + if (!existsSync(join(repository, file))) continue; + mkdirSync(dirname(join(root, file)), { recursive: true }); + copyFileSync(join(repository, file), join(root, file)); + } + for (const directory of configuration.links) { + mkdirSync(dirname(join(root, directory)), { recursive: true }); + symlinkSync(join(repository, directory), join(root, directory), "dir"); + } + const actualPackage = JSON.parse( + readFileSync(join(repository, "package.json"), "utf8"), + ); + writeFileSync(join(root, "package.json"), JSON.stringify(actualPackage)); + successful(root, "git", ["init", "--quiet"]); + successful(root, "git", ["config", "user.name", "Quality fixture"]); + successful(root, "git", [ + "config", + "user.email", + "quality-fixture@example.invalid", + ]); + successful(root, "git", [ + "-c", + "commit.gpgsign=false", + "commit", + "--quiet", + "--allow-empty", + "-m", + "fixture setup", + ]); + chmodSync(join(root, ".husky/pre-commit"), 0o755); + successful(root, process.execPath, [ + "tools/quality/node_modules/husky/bin.js", + ]); + assert.equal( + successful(root, "git", ["config", "--local", "core.hooksPath"]), + ".husky/_", + ); + assert.ok(statSync(join(root, ".husky/_/pre-commit")).mode & 0o111); + return root; +} + +/** Stage normalized fixture text so the intended lint rule, rather than unrelated formatting, refuses the commit. */ +function stage(root, files, source) { + for (const file of files) { + mkdirSync(dirname(join(root, file)), { recursive: true }); + writeFileSync(join(root, file), source); + } + successful(root, process.execPath, [ + "tools/quality/node_modules/prettier/bin/prettier.cjs", + "--write", + ...files, + ]); + successful(root, "git", ["add", "--", ...files]); +} + +/** A rejected commit must retain HEAD and identify every tested extension, preventing one covered file from masking an ignored peer. */ +function rejected(root, files, diagnostic) { + const head = successful(root, "git", ["rev-parse", "HEAD"]); + const result = command(root, "git", [ + "-c", + "commit.gpgsign=false", + "commit", + "--quiet", + "-m", + "reject invalid authored extensions", + ]); + const output = `${result.stdout}\n${result.stderr}`.replaceAll("\\", "/"); + assert.notEqual(result.status, 0, output); + assert.match(output, diagnostic); + for (const file of files) { + const sections = output + .split(/\n\s*\n/) + .filter((section) => section.includes(file)); + assert.ok( + sections.some((section) => diagnostic.test(section)), + `Missing intended diagnostic for ${file}:\n${output}`, + ); + } + assert.equal(successful(root, "git", ["rev-parse", "HEAD"]), head); + successful(root, "git", ["reset", "--quiet", "HEAD", "--", ...files]); + for (const file of files) rmSync(join(root, file)); +} + +/** Exercise actual commits for all authored extensions; strict TS boundaries additionally require their configured program. */ +test("installed pre-commit checks JavaScript and rejects unconfigured TypeScript", (t) => { + const root = fixture(t); + /** Keep fixture paths inside the actual source program and give each extension its own diagnostic. */ + const paths = (extensions) => + extensions.map( + (extension) => `${configuration.source}/hook-${extension}.${extension}`, + ); + const javascript = paths(["js", "jsx", "mjs", "cjs"]); + const typescript = paths(["ts", "tsx", "mts", "cts"]); + stage( + root, + javascript, + "const value = process.env.HOOK_FIXTURE_VALUE;\nconsole.log(value == 1);\n", + ); + rejected(root, javascript, /eqeqeq/); + stage( + root, + typescript, + "/** Preserve the supplied untrusted value. */\nexport function same(value: any) { return value; }\n", + ); + rejected(root, typescript, /TypeScript requires a configured strict program/); + + stage( + root, + javascript, + "const value = process.env.HOOK_FIXTURE_VALUE;\nconsole.log(value === 1);\n", + ); + successful(root, "git", [ + "-c", + "commit.gpgsign=false", + "commit", + "--quiet", + "-m", + "accept corrected authored extensions", + ]); +}); diff --git a/quality/typescript-policy.mjs b/quality/typescript-policy.mjs new file mode 100644 index 0000000..0abfaa1 --- /dev/null +++ b/quality/typescript-policy.mjs @@ -0,0 +1,24 @@ +import { execFileSync } from "node:child_process"; +import { relative, resolve } from "node:path"; + +// Native SDKs currently have no authored TypeScript. New TS must gain a strict program before it can enter the repository. +const requested = process.argv.slice(2); +const files = requested.length + ? requested + : execFileSync( + "git", + ["ls-files", "--cached", "--others", "--exclude-standard", "-z"], + { encoding: "utf8" }, + ).split("\0"); +/** Normalize lint-staged absolute paths before excluding the sealed vendor; repository-authored TS remains forbidden until a program exists. */ +const unsupported = files.filter((file) => { + const path = relative(process.cwd(), resolve(file)).replaceAll("\\", "/"); + return ( + /\.(?:ts|tsx|mts|cts)$/.test(path) && !path.startsWith("tools/quality/") + ); +}); +for (const file of unsupported) + console.error( + `${file}: TypeScript requires a configured strict program; preserve the native SDK profile and explicitly configure authored TS tooling first.`, + ); +if (unsupported.length) process.exitCode = 1; From 4da65464da840167a7acfee3cdb87411444cbb44 Mon Sep 17 00:00:00 2001 From: Alibek Seksenali Date: Tue, 13 Oct 2026 12:09:08 +0500 Subject: [PATCH 8/8] fix(quality): parse suppression comments with template context --- package.json | 3 +- quality/hooks.test.mjs | 1 + tools/quality/README.md | 20 ++++ tools/quality/lib/guards.mjs | 47 +++++++-- tools/quality/package-lock.json | 4 +- tools/quality/package.json | 2 +- tools/quality/staged.mjs | 43 ++++++++ tools/quality/template-manifest.json | 14 +-- tools/quality/test/cli.test.mjs | 74 ++++++++++++++ .../quality/test/suppression-syntax.test.mjs | 97 +++++++++++++++++++ 10 files changed, 285 insertions(+), 20 deletions(-) create mode 100644 tools/quality/staged.mjs create mode 100644 tools/quality/test/suppression-syntax.test.mjs diff --git a/package.json b/package.json index 7c32aa2..505c45f 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,9 @@ }, "lint-staged": { "*.{js,jsx,mjs,cjs}": [ + "node tools/quality/staged.mjs --config eslint.config.mjs --", "node tools/quality/node_modules/prettier/bin/prettier.cjs --write", - "node tools/quality/node_modules/eslint/bin/eslint.js --config eslint.config.mjs --max-warnings=0" + "node tools/quality/node_modules/eslint/bin/eslint.js --config eslint.config.mjs --max-warnings=0 --no-warn-ignored" ], "*.{ts,tsx,mts,cts}": [ "node quality/typescript-policy.mjs" diff --git a/quality/hooks.test.mjs b/quality/hooks.test.mjs index 8ef4fea..416388e 100644 --- a/quality/hooks.test.mjs +++ b/quality/hooks.test.mjs @@ -23,6 +23,7 @@ const configuration = { typed: false, files: [ "package.json", + "quality.config.mjs", "quality/typescript-policy.mjs", ".husky/pre-commit", "eslint.config.mjs", diff --git a/tools/quality/README.md b/tools/quality/README.md index 9c78337..750bd5c 100644 --- a/tools/quality/README.md +++ b/tools/quality/README.md @@ -150,3 +150,23 @@ not modify the runtime Git driver or skip checks on Windows. Only fixture setup changes: analysis rules, historical identities and baseline records are unchanged. Copy the complete sealed version without changing debt owners, reasons, issue links, expiry dates or baseline entries. + +## 1.0.12 migration + +Suppression detection now scans trivia between parsed TypeScript tokens. A plain +scanner loses context after a template interpolation: it can mistake generated +directive text for a source comment and overlook a real directive after the +template. Parsed template segments, regex bodies and JSX text remain data; +comments inside interpolations/JSX expressions and at EOF remain enforceable. +Positive and negative syntax fixtures and the real guard CLI cover both failure +modes, including scoped exception requirements and Svelte script blocks. +Copy the complete sealed version. Metric identities, source coverage and debt +allowances do not change; rerun guards to detect any previously missed comments. + +The staged-file coverage preflight (`staged.mjs --config -- +`) permits ignored files only when the repository inventory explicitly +declares them or they belong to the verified sealed preset. Run it before ESLint +with `--no-warn-ignored`: this supports preset updates and generated files while +still rejecting an accidentally ignored authored file. An added or altered +unsealed vendor file fails integrity validation; an arbitrary ESLint ignore alone +never grants an exemption. diff --git a/tools/quality/lib/guards.mjs b/tools/quality/lib/guards.mjs index 69e3bde..0e3fddb 100644 --- a/tools/quality/lib/guards.mjs +++ b/tools/quality/lib/guards.mjs @@ -280,29 +280,56 @@ function historicalFunctions(path, text) { } } -/** Identify suppression directives in comments only, never in strings or generated documentation examples. */ -export function suppressionErrors(path, text, config) { - const errors = []; - for (const { ast } of parseUnits(path, text)) { +/** Yield parsed lexical leaves without descending into documentation or splitting literal/JSX content. */ +function* syntaxTokens(node, ast) { + if ( + (node.kind >= ts.SyntaxKind.FirstJSDocNode && + node.kind <= ts.SyntaxKind.LastJSDocNode) || + node.kind === ts.SyntaxKind.JSDocComment + ) + return; + const children = node.getChildren(ast); + if (children.length) { + for (const child of children) yield* syntaxTokens(child, ast); + } else if (node.kind !== ts.SyntaxKind.SyntaxList) { + yield node; + } +} + +/** Scan only trivia between parsed tokens; interpolation expressions retain comments while template/regex/JSX bodies stay opaque. */ +function* sourceComments(ast) { + let end = 0; + for (const token of syntaxTokens(ast, ast)) { + const start = token.getStart(ast); const scanner = ts.createScanner( ts.ScriptTarget.Latest, false, ts.LanguageVariant.Standard, - ast.text, + ast.text.slice(end, start), ); for ( - let token = scanner.scan(); - token !== ts.SyntaxKind.EndOfFileToken; - token = scanner.scan() + let trivia = scanner.scan(); + trivia !== ts.SyntaxKind.EndOfFileToken; + trivia = scanner.scan() ) { if ( ![ ts.SyntaxKind.SingleLineCommentTrivia, ts.SyntaxKind.MultiLineCommentTrivia, - ].includes(token) + ].includes(trivia) ) continue; - const comment = scanner.getTokenText(); + yield scanner.getTokenText(); + } + end = token.end; + } +} + +/** Identify suppression directives in comments only, never in strings or generated documentation examples. */ +export function suppressionErrors(path, text, config) { + const errors = []; + for (const { ast } of parseUnits(path, text)) { + for (const comment of sourceComments(ast)) { if ( /@ts-(?:ignore|nocheck)\b/.test(comment) || /eslint-disable(?!-next-line|-line)\b/.test(comment) diff --git a/tools/quality/package-lock.json b/tools/quality/package-lock.json index 527d33a..bf75285 100644 --- a/tools/quality/package-lock.json +++ b/tools/quality/package-lock.json @@ -1,12 +1,12 @@ { "name": "@1msg/quality-template", - "version": "1.0.11", + "version": "1.0.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@1msg/quality-template", - "version": "1.0.11", + "version": "1.0.12", "dependencies": { "@eslint/js": "9.39.5", "dependency-cruiser": "18.6.0", diff --git a/tools/quality/package.json b/tools/quality/package.json index 67942c0..f6bbd11 100644 --- a/tools/quality/package.json +++ b/tools/quality/package.json @@ -1,6 +1,6 @@ { "name": "@1msg/quality-template", - "version": "1.0.11", + "version": "1.0.12", "private": true, "type": "module", "engines": { diff --git a/tools/quality/staged.mjs b/tools/quality/staged.mjs new file mode 100644 index 0000000..bbfa798 --- /dev/null +++ b/tools/quality/staged.mjs @@ -0,0 +1,43 @@ +import { ESLint } from 'eslint'; +import { readFileSync, existsSync } from 'node:fs'; +import { relative, resolve } from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { matches } from './lib/guards.mjs'; +import { verifyTemplate } from './lib/template.mjs'; + +const [, , flag, configuration, separator, ...files] = process.argv; +if (flag !== '--config' || !configuration || separator !== '--') + throw new Error('Usage: staged.mjs --config -- '); + +const { default: inventory } = await import( + pathToFileURL(resolve('quality.config.mjs')).href +); +const approved = [ + ...(inventory.generated ?? []), + ...(inventory.excluded ?? []), +].map((entry) => entry.pattern); +const manifestPath = 'tools/quality/template-manifest.json'; +let vendorFiles = new Set(); +if (existsSync(manifestPath)) { + verifyTemplate('HEAD'); + const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); + vendorFiles = new Set([ + manifestPath, + ...Object.keys(manifest.files).map((path) => `tools/quality/${path}`), + ]); +} +const eslint = new ESLint({ overrideConfigFile: configuration }); +const uncovered = []; +for (const file of files) { + const path = relative(process.cwd(), resolve(file)).replaceAll('\\', '/'); + if ( + (await eslint.isPathIgnored(file)) && + !vendorFiles.has(path) && + !matches(path, approved) + ) + uncovered.push(path); +} +if (uncovered.length) + throw new Error( + `Staged authored files have no ESLint coverage:\n${uncovered.join('\n')}`, + ); diff --git a/tools/quality/template-manifest.json b/tools/quality/template-manifest.json index 210f229..4e79096 100644 --- a/tools/quality/template-manifest.json +++ b/tools/quality/template-manifest.json @@ -1,29 +1,31 @@ { "schemaVersion": 1, - "version": "1.0.11", + "version": "1.0.12", "files": { - "README.md": "6760e252841ba82078ede1589a474dd19c8f77f828245e181f34e842465c3aa1", + "README.md": "80380757947a33100e4f43f7808b129f2c3cdc81c380614fc2e55153ef5f124a", "canonical-duplicates.mjs": "a3583fdc3e344af448ea8d2543c2398daaa03fa10a0739da486afb04e35425ba", "complexity.mjs": "4ed5553c392621e0615a48c12e12300c8602ed2a28cfbaff67002acf82e49cac", "eslint.mjs": "607ddfaac3d365fedd7dbc5e21c781d448347b1c36662f3492e4364ff9f22ded", "lib/baseline.mjs": "7876ba90b80448d9c9003c21e348095ed22630c41fc26ed944984742020549dd", "lib/git.mjs": "b7c26871526d864bf8d12f01c613d3bfa0adb2da9d072544d8f09407ef598758", - "lib/guards.mjs": "b1b025a1fdcb63434733216a4faaa45112aa404f26f9d31df28921243d6a22f8", + "lib/guards.mjs": "fe95129ef78aa5354446d8b37769ac27deb95d2b8bc978c5d3bafad538bd7836", "lib/historical.mjs": "43b46395828daa3f19d8692e9bd22ea6cfc1d0dbac83814d727894f672a0ddd2", "lib/knip-reporter.mjs": "175d7d96e2913e8f6de04b6c706172258d9d7654a26ba7f9ed7edff79d3fc8ca", "lib/reports.mjs": "361e38ae981238db91f7b9a31af963ccbb89e3ae6745d1582b2086e6c64f0c9e", "lib/template.mjs": "c2a14b715f0c9dbe8b8243b142f4c6628967400fb8f92767537169e1b7bfd8f4", - "package-lock.json": "9fc7d279d2bade1c42f807d99a107d77f15a8e42edd2a9b32b4b5ce1a4fda35f", - "package.json": "deb5fd5e972aec2926b21e31d02c47e9c35d507048e83ab0ed161425151546e2", + "package-lock.json": "238e6a8ff9303c66968b8e83ef028dfa49b7bb6a5ca485c0a7e65520d4c54365", + "package.json": "91adacf496715638a7e765035ca16d27e7a3c40ad3abbdd4bb4fc8c9574113eb", "prettier.config.mjs": "7576563a9a30aff8eb3177f9cc2e4bc7a0f6b825042eadb9a619b86f519c5e5e", "run.mjs": "7cf26128cdf63f3a7ccab7341a0a274a352fd9bda0521ba41e37216bb9cc249f", "seal.mjs": "fb38c8e08ea3cf9f4dcd95e45ffc931aea3b7a54181fed88d7379f8aad4c050d", - "test/cli.test.mjs": "49c55b1b4cf2ca2214b0f1b5d2bd973eac43005e14606f27a2a4aa682e0e691d", + "staged.mjs": "17db5c61a1369e6e740fd233887eca0033b64f2114dd3871b96108afb6123d49", + "test/cli.test.mjs": "a8e066e20790fc0d915b6a6d7ba11ca8d2af2a59ca6d51f4da232e7efb511f39", "test/complexity.test.mjs": "ba1f702ba94de3fcad93cb5e43a49bc2456be1426c81754149420d210f2b3952", "test/git-portability.test.mjs": "0e65759ff3a1aa87c20d20ae147154d980381c2e8075f57f341ef3c53c3b3f62", "test/guard-history.test.mjs": "00b17403b3ef17cc5d83c681c990ca98b6a0ad4857a95d501d2cf8f390aa7b1e", "test/ratchet.test.mjs": "324a932c5a52d1b037e111042e1b41e5686f8d4dbfd0307faf86cee649ebc27a", "test/reports.test.mjs": "521a13da2f16628b4a30de7040529e0b7b7e25e7db79d19de8004945d49c5e0c", + "test/suppression-syntax.test.mjs": "1b3dfc3a66ee9978491402e3683511c2d3a6d42203b283cd4a74578551a197b0", "tsconfig.next.json": "d900a35fcb0852376b06854df5be2f8f178e26cb5383b93b07ebeb6220e30faf", "tsconfig.node.json": "627661abcb7e992c4bfaf98d6e68a12678573b5d4f6e821ea0fa43fa6e233f28", "tsconfig.svelte.json": "5777247ea98aaf2d886b87cd12206a641377edcdd086ce5fd5b58adc6f0bc771" diff --git a/tools/quality/test/cli.test.mjs b/tools/quality/test/cli.test.mjs index 0c8d1cd..88b6aa6 100644 --- a/tools/quality/test/cli.test.mjs +++ b/tools/quality/test/cli.test.mjs @@ -99,6 +99,80 @@ test('real CLI blocks undocumented new functions, broad suppression and uncovere } }); +/** The real guard CLI distinguishes generated directive text from actual suppressions in and after interpolations. */ +test('actual guards CLI enforces comments around interpolated template data', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + const base = f.commit(); + f.write( + 'src/index.js', + 'const generated = `a ${name} /* eslint-disable */`;\nconsole.log(generated);\n', + ); + const valid = f.run('guards', '--base', base); + assert.equal(valid.status, 0, valid.stderr); + for (const source of [ + 'const generated = `a ${ /* eslint-disable */ name } z`;\n', + 'const generated = `a ${name} z`; // @ts-nocheck\n', + ]) { + f.write('src/index.js', source); + const invalid = f.run('guards', '--base', base); + assert.equal(invalid.status, 1, invalid.stderr); + assert.match(invalid.stderr, /broad lint\/type suppression/); + } + } finally { + f.close(); + } +}); + +/** The actual staged preflight permits declared generated sources while rejecting ordinary ESLint ignores. */ +test('staged coverage rejects unowned ignores and validates sealed vendor files', () => { + const f = fixture(); + try { + f.write('src/index.js', 'console.log("app");\n'); + f.commit(); + f.write( + 'eslint.config.mjs', + 'export default [{ignores:["src/ignored.js","src/generated.js","tools/quality/**"]}];\n', + ); + f.write( + 'quality.config.mjs', + 'export default {generated:[{pattern:"src/generated.js",producer:"fixture"}]};\n', + ); + f.write('src/ignored.js', 'export const forgotten = 1;\n'); + f.write('src/generated.js', 'export const generated = 1;\n'); + const staged = fileURLToPath(new URL('../staged.mjs', import.meta.url)); + /** Invoke the installed ESLint resolver and real sealed inventory with only disposable files. */ + const check = (path) => + spawnSync( + process.execPath, + [staged, '--config', 'eslint.config.mjs', '--', path], + { cwd: f.cwd, encoding: 'utf8' }, + ); + assert.equal(check('src/index.js').status, 0); + assert.equal(check('src/generated.js').status, 0); + const ignored = check('src/ignored.js'); + assert.equal(ignored.status, 1); + assert.match( + ignored.stderr, + /Staged authored files have no ESLint coverage/, + ); + const template = fileURLToPath(new URL('..', import.meta.url)); + for (const path of [...templateFiles(template), 'template-manifest.json']) { + const destination = join(f.cwd, 'tools/quality', path); + mkdirSync(dirname(destination), { recursive: true }); + cpSync(join(template, path), destination); + } + assert.equal(check('tools/quality/lib/guards.mjs').status, 0); + f.write('tools/quality/rogue.js', 'export const bypass = 1;\n'); + const rogue = check('tools/quality/rogue.js'); + assert.equal(rogue.status, 1); + assert.match(rogue.stderr, /undeclared\/missing files/); + } finally { + f.close(); + } +}); + test('actual Knip CLI blocks an unused file and unresolved import', () => { const f = fixture(); try { diff --git a/tools/quality/test/suppression-syntax.test.mjs b/tools/quality/test/suppression-syntax.test.mjs new file mode 100644 index 0000000..4d5b0bf --- /dev/null +++ b/tools/quality/test/suppression-syntax.test.mjs @@ -0,0 +1,97 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { suppressionErrors } from '../lib/guards.mjs'; + +/** Template segments, regex bodies and JSX text are data even when they contain directive spelling. */ +test('suppression scanning preserves parsed literal boundaries', () => { + const sources = [ + [ + 'a.js', + 'const generated = `start ${name}\n/* eslint-disable */\n// @ts-nocheck\n`;', + ], + [ + 'a.ts', + 'const generated = `a ${`b ${name}\n// @ts-ignore\n`} c ${name} /* eslint-disable */`;', + ], + [ + 'a.mjs', + 'const generated = tag`head ${name}\n// @ts-nocheck\n${other} /* eslint-disable */`;', + ], + [ + 'a.ts', + String.raw`const pattern = /[/*]eslint-disable/; const other = /[//]@ts-ignore/;`, + ], + [ + 'a.tsx', + 'const view =
// @ts-ignore {name}/* eslint-disable */
;', + ], + [ + 'a.jsx', + 'const view =
{/* ordinary comment */} // @ts-ignore
;', + ], + [ + 'a.svelte', + '', + ], + ]; + for (const [path, source] of sources) { + assert.deepEqual( + suppressionErrors(path, source, {}), + [], + `${path}: ${source}`, + ); + } +}); + +/** Actual comments remain enforceable before, within and after expressions, including EOF trivia. */ +test('suppression scanning rejects comments inside template and JSX expressions', () => { + const sources = [ + ['a.js', 'const generated = `a ${ /* eslint-disable */ name } z`;'], + [ + 'a.ts', + 'const generated = `a ${`b ${ /* eslint-disable */ name } c`} d`;', + ], + ['a.mjs', 'const generated = `a ${name // @ts-ignore\n} z`;'], + ['a.cts', 'const generated = `a ${name} z`; // @ts-nocheck'], + ['a.tsx', 'const view =
{/* eslint-disable */ name}
;'], + ['a.jsx', 'const view =
;\n// @ts-ignore'], + ['a.ts', '/* eslint-disable */'], + [ + 'a.ts', + '/** @ts-ignore This comment is real documentation. */\nconst value = 1;', + ], + [ + 'a.ts', + String.raw`const pattern = /[/*]/; /* eslint-disable */ const value = 1;`, + ], + [ + 'a.svelte', + '', + ], + ]; + for (const [path, source] of sources) { + assert.equal( + suppressionErrors(path, source, {}).length, + 1, + `${path}: ${source}`, + ); + } +}); + +/** Malformed scoped comments must not gain an exemption merely by appearing in an interpolation. */ +test('suppression scanning retains scoped exception requirements', () => { + const source = 'const generated = `a ${ // eslint-disable-next-line\nname }`'; + assert.match(suppressionErrors('a.ts', source, {})[0], /must name rules/); + const negative = + 'const generated = `a ${ // @ts-expect-error: Verify an invalid primitive contract\nname }`'; + assert.match( + suppressionErrors('a.ts', negative, {})[0], + /negative type-test scope/, + ); + assert.deepEqual( + suppressionErrors('negative.test.ts', negative, { + negativeTypeTests: ['*.test.ts'], + }), + [], + ); +});