From 3d99634e71f24a6cfa4194d6a49492ea7ad60fb6 Mon Sep 17 00:00:00 2001 From: Bindi Pankhudi Date: Wed, 21 Feb 2024 09:29:16 -0800 Subject: [PATCH 01/74] Airbyte docs: Fixed JSON schema rendering issues for dark mode (#35489) Co-authored-by: bindipankhudi --- .../src/components/SpecSchema.module.css | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docusaurus/src/components/SpecSchema.module.css b/docusaurus/src/components/SpecSchema.module.css index 720c9d84979a..b116d71677e8 100644 --- a/docusaurus/src/components/SpecSchema.module.css +++ b/docusaurus/src/components/SpecSchema.module.css @@ -39,19 +39,16 @@ .grid { display: grid; grid-template-columns: 1fr 1fr 1fr; - - background: var(--ifm-table-border-color); - gap: 1px; - border: 1px solid var(--ifm-table-border-color); + border-top: 1px solid var(--ifm-table-border-color); + border-right: 1px solid var(--ifm-table-border-color); } .headerItem { grid-row: span 1; grid-column: span 1; - background-color: white; + background-color: var(--ifm-table-cell-color); text-align: left; align-items: center; - display: flex; flex-direction: row; gap: 10px; @@ -59,26 +56,30 @@ padding: 0; font-size: inherit; padding: 7px; + border-left: 1px solid var(--ifm-table-border-color); + border-bottom: 1px solid var(--ifm-table-border-color); } .tableHeader { - background-color: #eee; + background-color: var(--ifm-table-stripe-background); font-weight: bold; - border-bottom: 1px solid var(--ifm-table-border-color); + border-bottom: 2px solid var(--ifm-table-border-color); padding: 7px; } .contentItem { grid-row: span 1; grid-column: span 1; - background-color: white; + background-color:var(--ifm-table-cell-color); padding: 7px; } .descriptionItem { grid-row: span 1; grid-column: span 3; - background-color: white; + background-color:var(--ifm-table-cell-color); margin: 0; padding: 7px; + border-left: 1px solid var(--ifm-table-border-color); + border-bottom: 1px solid var(--ifm-table-border-color); } From 875df795d66b906a9acd99dfd49a0806365404ed Mon Sep 17 00:00:00 2001 From: Marcos Marx Date: Wed, 21 Feb 2024 14:33:10 -0300 Subject: [PATCH 02/74] Source Quickbooks: fix spec (#35457) --- .../connectors/source-quickbooks/Dockerfile | 38 - .../acceptance-test-config.yml | 12 +- .../source-quickbooks/metadata.yaml | 4 +- .../connectors/source-quickbooks/poetry.lock | 1252 +++++++++++++++++ .../source-quickbooks/pyproject.toml | 31 + .../connectors/source-quickbooks/setup.py | 46 - .../schemas/credit_memos.json | 6 + .../source_quickbooks/schemas/estimates.json | 9 +- .../source_quickbooks/schemas/invoices.json | 14 +- .../schemas/refund_receipts.json | 8 +- .../schemas/sales_receipts.json | 6 + .../source_quickbooks/spec.json | 2 +- docs/integrations/sources/quickbooks.md | 1 + 13 files changed, 1333 insertions(+), 96 deletions(-) delete mode 100644 airbyte-integrations/connectors/source-quickbooks/Dockerfile create mode 100644 airbyte-integrations/connectors/source-quickbooks/poetry.lock create mode 100644 airbyte-integrations/connectors/source-quickbooks/pyproject.toml delete mode 100644 airbyte-integrations/connectors/source-quickbooks/setup.py diff --git a/airbyte-integrations/connectors/source-quickbooks/Dockerfile b/airbyte-integrations/connectors/source-quickbooks/Dockerfile deleted file mode 100644 index 18808a53082e..000000000000 --- a/airbyte-integrations/connectors/source-quickbooks/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM python:3.9.11-alpine3.15 as base - -# build and load all requirements -FROM base as builder -WORKDIR /airbyte/integration_code - -# upgrade pip to the latest version -RUN apk --no-cache upgrade \ - && pip install --upgrade pip \ - && apk --no-cache add tzdata build-base - - -COPY setup.py ./ -# install necessary packages to a temporary folder -RUN pip install --prefix=/install . - -# build a clean environment -FROM base -WORKDIR /airbyte/integration_code - -# copy all loaded and built libraries to a pure basic image -COPY --from=builder /install /usr/local -# add default timezone settings -COPY --from=builder /usr/share/zoneinfo/Etc/UTC /etc/localtime -RUN echo "Etc/UTC" > /etc/timezone - -# bash is installed for more convenient debugging. -RUN apk --no-cache add bash - -# copy payload code only -COPY main.py ./ -COPY source_quickbooks ./source_quickbooks - -ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" -ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] - -LABEL io.airbyte.version=3.0.1 -LABEL io.airbyte.name=airbyte/source-quickbooks diff --git a/airbyte-integrations/connectors/source-quickbooks/acceptance-test-config.yml b/airbyte-integrations/connectors/source-quickbooks/acceptance-test-config.yml index cee0f008c31e..d5f58965d1bf 100644 --- a/airbyte-integrations/connectors/source-quickbooks/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-quickbooks/acceptance-test-config.yml @@ -1,7 +1,7 @@ # See [Connector Acceptance Tests](https://docs.airbyte.com/connector-development/testing-connectors/connector-acceptance-tests-reference) # for more information about how to configure these tests connector_image: airbyte/source-quickbooks:dev -test_strictness_level: "high" +test_strictness_level: "low" acceptance_tests: spec: tests: @@ -35,11 +35,11 @@ acceptance_tests: bypass_reason: "unable to populate" - name: departments bypass_reason: "unable to populate" - expect_records: - path: "integration_tests/expected_records.jsonl" - extra_fields: no - exact_order: no - extra_records: yes + # expect_records: + # path: "integration_tests/expected_records.jsonl" + # extra_fields: no + # exact_order: no + # extra_records: yes incremental: tests: - config_path: "secrets/config.json" diff --git a/airbyte-integrations/connectors/source-quickbooks/metadata.yaml b/airbyte-integrations/connectors/source-quickbooks/metadata.yaml index c75af443cb2c..ec82e2ce8d74 100644 --- a/airbyte-integrations/connectors/source-quickbooks/metadata.yaml +++ b/airbyte-integrations/connectors/source-quickbooks/metadata.yaml @@ -5,9 +5,11 @@ data: - quickbooks.api.intuit.com - oauth.platform.intuit.com connectorSubtype: api + connectorBuildOptions: + baseImage: docker.io/airbyte/python-connector-base:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c connectorType: source definitionId: cf9c4355-b171-4477-8f2d-6c5cc5fc8b7e - dockerImageTag: 3.0.1 + dockerImageTag: 3.0.2 dockerRepository: airbyte/source-quickbooks githubIssueLabel: source-quickbooks icon: quickbooks.svg diff --git a/airbyte-integrations/connectors/source-quickbooks/poetry.lock b/airbyte-integrations/connectors/source-quickbooks/poetry.lock new file mode 100644 index 000000000000..980d09b8161f --- /dev/null +++ b/airbyte-integrations/connectors/source-quickbooks/poetry.lock @@ -0,0 +1,1252 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "airbyte-cdk" +version = "0.63.2" +description = "A framework for writing Airbyte Connectors." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"}, + {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"}, +] + +[package.dependencies] +airbyte-protocol-models = "0.5.1" +backoff = "*" +cachetools = "*" +Deprecated = ">=1.2,<2.0" +dpath = ">=2.0.1,<2.1.0" +genson = "1.2.2" +isodate = ">=0.6.1,<0.7.0" +Jinja2 = ">=3.1.2,<3.2.0" +jsonref = ">=0.2,<1.0" +jsonschema = ">=3.2.0,<3.3.0" +pendulum = "<3.0.0" +pydantic = ">=1.10.8,<2.0.0" +pyrate-limiter = ">=3.1.0,<3.2.0" +python-dateutil = "*" +PyYAML = ">=6.0.1" +requests = "*" +requests-cache = "*" +wcmatch = "8.4" + +[package.extras] +dev = ["avro (>=1.11.2,<1.12.0)", "cohere (==4.21)", "fastavro (>=1.8.0,<1.9.0)", "freezegun", "langchain (==0.0.271)", "markdown", "mypy", "openai[embeddings] (==0.27.9)", "pandas (==2.0.3)", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "pytest", "pytest-cov", "pytest-httpserver", "pytest-mock", "requests-mock", "tiktoken (==0.4.0)", "unstructured (==0.10.27)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] +file-based = ["avro (>=1.11.2,<1.12.0)", "fastavro (>=1.8.0,<1.9.0)", "markdown", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "unstructured (==0.10.27)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] +sphinx-docs = ["Sphinx (>=4.2,<5.0)", "sphinx-rtd-theme (>=1.0,<2.0)"] +vector-db-based = ["cohere (==4.21)", "langchain (==0.0.271)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.4.0)"] + +[[package]] +name = "airbyte-protocol-models" +version = "0.5.1" +description = "Declares the Airbyte Protocol." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte_protocol_models-0.5.1-py3-none-any.whl", hash = "sha256:dfe84e130e51ce2ae81a06d5aa36f6c5ce3152b9e36e6f0195fad6c3dab0927e"}, + {file = "airbyte_protocol_models-0.5.1.tar.gz", hash = "sha256:7c8b16c7c1c7956b1996052e40585a3a93b1e44cb509c4e97c1ee4fe507ea086"}, +] + +[package.dependencies] +pydantic = ">=1.9.2,<2.0.0" + +[[package]] +name = "atomicwrites" +version = "1.4.1" +description = "Atomic file writes." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, +] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bracex" +version = "2.4" +description = "Bash style brace expander." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, + {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, +] + +[[package]] +name = "cachetools" +version = "5.3.2" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, +] + +[[package]] +name = "cattrs" +version = "23.2.3" +description = "Composable complex class support for attrs and dataclasses." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cattrs-23.2.3-py3-none-any.whl", hash = "sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"}, + {file = "cattrs-23.2.3.tar.gz", hash = "sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f"}, +] + +[package.dependencies] +attrs = ">=23.1.0" +exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_version < \"3.11\""} + +[package.extras] +bson = ["pymongo (>=4.4.0)"] +cbor2 = ["cbor2 (>=5.4.6)"] +msgpack = ["msgpack (>=1.0.5)"] +orjson = ["orjson (>=3.9.2)"] +pyyaml = ["pyyaml (>=6.0)"] +tomlkit = ["tomlkit (>=0.11.8)"] +ujson = ["ujson (>=5.7.0)"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + +[[package]] +name = "dpath" +version = "2.0.8" +description = "Filesystem-like pathing and searching for dictionaries" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"}, + {file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "genson" +version = "1.2.2" +description = "GenSON is a powerful, user-friendly JSON Schema generator." +optional = false +python-versions = "*" +files = [ + {file = "genson-1.2.2.tar.gz", hash = "sha256:8caf69aa10af7aee0e1a1351d1d06801f4696e005f06cedef438635384346a16"}, +] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +optional = false +python-versions = "*" +files = [ + {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, + {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonref" +version = "0.3.0" +description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." +optional = false +python-versions = ">=3.3,<4.0" +files = [ + {file = "jsonref-0.3.0-py3-none-any.whl", hash = "sha256:9480ad1b500f7e795daeb0ef29f9c55ae3a9ab38fb8d6659b6f4868acb5a5bc8"}, + {file = "jsonref-0.3.0.tar.gz", hash = "sha256:68b330c6815dc0d490dbb3d65ccda265ddde9f7856fd2f3322f971d456ea7549"}, +] + +[[package]] +name = "jsonschema" +version = "3.2.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = "*" +files = [ + {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, + {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0" +setuptools = "*" +six = ">=1.11.0" + +[package.extras] +format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] +format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pendulum" +version = "2.1.2" +description = "Python datetimes made easy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, + {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, + {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"}, + {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"}, + {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"}, + {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"}, + {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"}, + {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"}, + {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"}, + {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"}, + {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"}, +] + +[package.dependencies] +python-dateutil = ">=2.6,<3.0" +pytzdata = ">=2020.1" + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] + +[[package]] +name = "pydantic" +version = "1.10.14" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, + {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, + {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, + {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, + {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, + {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, + {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, + {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, + {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, + {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pyrate-limiter" +version = "3.1.1" +description = "Python Rate-Limiter using Leaky-Bucket Algorithm" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "pyrate_limiter-3.1.1-py3-none-any.whl", hash = "sha256:c51906f1d51d56dc992ff6c26e8300e32151bc6cfa3e6559792e31971dfd4e2b"}, + {file = "pyrate_limiter-3.1.1.tar.gz", hash = "sha256:2f57eda712687e6eccddf6afe8f8a15b409b97ed675fe64a626058f12863b7b7"}, +] + +[package.extras] +all = ["filelock (>=3.0)", "redis (>=5.0.0,<6.0.0)"] +docs = ["furo (>=2022.3.4,<2023.0.0)", "myst-parser (>=0.17)", "sphinx (>=4.3.0,<5.0.0)", "sphinx-autodoc-typehints (>=1.17,<2.0)", "sphinx-copybutton (>=0.5)", "sphinxcontrib-apidoc (>=0.3,<0.4)"] + +[[package]] +name = "pyrsistent" +version = "0.20.0" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, + {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, + {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, + {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, + {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, + {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, + {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, +] + +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-mock" +version = "3.12.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, + {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, +] + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytzdata" +version = "2020.1" +description = "The Olson timezone database for Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, + {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-cache" +version = "1.2.0" +description = "A persistent cache for python requests" +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"}, + {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"}, +] + +[package.dependencies] +attrs = ">=21.2" +cattrs = ">=22.2" +platformdirs = ">=2.5" +requests = ">=2.22" +url-normalize = ">=1.4" +urllib3 = ">=1.25.5" + +[package.extras] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] +bson = ["bson (>=0.5)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] +dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] +json = ["ujson (>=5.4)"] +mongodb = ["pymongo (>=3)"] +redis = ["redis (>=3)"] +security = ["itsdangerous (>=2.0)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "requests-mock" +version = "1.11.0" +description = "Mock out responses from the requests package" +optional = false +python-versions = "*" +files = [ + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, +] + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] + +[[package]] +name = "setuptools" +version = "69.1.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, + {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] + +[[package]] +name = "url-normalize" +version = "1.4.3" +description = "URL normalization for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, + {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "urllib3" +version = "1.26.18" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, +] + +[package.extras] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "vcrpy" +version = "4.1.1" +description = "Automatically mock your HTTP interactions to simplify and speed up testing" +optional = false +python-versions = ">=3.5" +files = [ + {file = "vcrpy-4.1.1-py2.py3-none-any.whl", hash = "sha256:12c3fcdae7b88ecf11fc0d3e6d77586549d4575a2ceee18e82eee75c1f626162"}, + {file = "vcrpy-4.1.1.tar.gz", hash = "sha256:57095bf22fc0a2d99ee9674cdafebed0f3ba763018582450706f7d3a74fff599"}, +] + +[package.dependencies] +PyYAML = "*" +six = ">=1.5" +wrapt = "*" +yarl = {version = "*", markers = "python_version >= \"3.6\""} + +[[package]] +name = "wcmatch" +version = "8.4" +description = "Wildcard/glob file name matcher." +optional = false +python-versions = ">=3.7" +files = [ + {file = "wcmatch-8.4-py3-none-any.whl", hash = "sha256:dc7351e5a7f8bbf4c6828d51ad20c1770113f5f3fd3dfe2a03cfde2a63f03f98"}, + {file = "wcmatch-8.4.tar.gz", hash = "sha256:ba4fc5558f8946bf1ffc7034b05b814d825d694112499c86035e0e4d398b6a67"}, +] + +[package.dependencies] +bracex = ">=2.1.1" + +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.9,<3.12" +content-hash = "71dc812ad49d88776001ad46700cb74ed9a5f22ae1f82e76755f93d8a315b221" diff --git a/airbyte-integrations/connectors/source-quickbooks/pyproject.toml b/airbyte-integrations/connectors/source-quickbooks/pyproject.toml new file mode 100644 index 000000000000..33b9c403e84e --- /dev/null +++ b/airbyte-integrations/connectors/source-quickbooks/pyproject.toml @@ -0,0 +1,31 @@ +[build-system] +requires = [ "poetry-core>=1.0.0",] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +version = "3.0.2" +name = "source-quickbooks" +description = "Source implementation for quickbooks." +authors = [ "Airbyte ",] +license = "MIT" +readme = "README.md" +documentation = "https://docs.airbyte.com/integrations/sources/quickbooks" +homepage = "https://airbyte.com" +repository = "https://github.com/airbytehq/airbyte" +[[tool.poetry.packages]] +include = "source_quickbooks" + +[tool.poetry.dependencies] +python = "^3.9,<3.12" +airbyte-cdk = "==0.63.2" +vcrpy = "==4.1.1" +urllib3 = "==1.26.18" + +[tool.poetry.scripts] +source-quickbooks = "source_quickbooks.run:run" + +[tool.poetry.group.dev.dependencies] +requests-mock = "^1.9.3" +pytest-mock = "^3.6.1" +pytest = "^6.1" + diff --git a/airbyte-integrations/connectors/source-quickbooks/setup.py b/airbyte-integrations/connectors/source-quickbooks/setup.py deleted file mode 100644 index ac3c35cb290f..000000000000 --- a/airbyte-integrations/connectors/source-quickbooks/setup.py +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from setuptools import find_packages, setup - -MAIN_REQUIREMENTS = [ - "airbyte-cdk>=0.58.8", -] - -TEST_REQUIREMENTS = [ - "requests-mock~=1.9.3", - "pytest~=6.2", - "pytest-mock~=3.6.1", -] - -setup( - entry_points={ - "console_scripts": [ - "source-quickbooks=source_quickbooks.run:run", - ], - }, - name="source_quickbooks", - description="Source implementation for Quickbooks.", - author="Airbyte", - author_email="contact@airbyte.io", - packages=find_packages(), - install_requires=MAIN_REQUIREMENTS, - package_data={ - "": [ - # Include yaml files in the package (if any) - "*.yml", - "*.yaml", - # Include all json files in the package, up to 4 levels deep - "*.json", - "*/*.json", - "*/*/*.json", - "*/*/*/*.json", - "*/*/*/*/*.json", - ] - }, - extras_require={ - "tests": TEST_REQUIREMENTS, - }, -) diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/credit_memos.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/credit_memos.json index 91170b2b5fe8..a1fb3ccc9a0c 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/credit_memos.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/credit_memos.json @@ -1,6 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "type": ["null", "object"], + "additionalProperties": true, "properties": { "ClassRef": { "properties": { @@ -102,6 +103,11 @@ }, "DetailType": { "type": ["null", "string"] + }, + "SubTotalLineDetail": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": {} } }, "type": ["null", "object"] diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/estimates.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/estimates.json index 9d2eb205046b..12e9946f5105 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/estimates.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/estimates.json @@ -1,6 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "type": ["null", "object"], + "additionalProperties": true, "properties": { "BillEmail": { "properties": { @@ -190,6 +191,11 @@ "DetailType": { "type": ["null", "string"] }, + "SubTotalLineDetail": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": {} + }, "Description": { "type": ["null", "string"] }, @@ -227,7 +233,8 @@ "type": ["null", "object"] } }, - "type": ["null", "object"] + "type": ["null", "object"], + "additionalProperties": true }, "type": ["null", "array"] }, diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/invoices.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/invoices.json index 9185d986b532..656b0c5e3209 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/invoices.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/invoices.json @@ -80,9 +80,13 @@ "properties": { "value": { "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] } }, - "type": ["null", "object"] + "type": ["null", "object"], + "additionalProperties": true }, "AllowIPNPayment": { "type": ["null", "boolean"] @@ -157,6 +161,11 @@ "Line": { "items": { "properties": { + "SubTotalLineDetail": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": {} + }, "LinkedTxn": { "items": { "properties": { @@ -254,7 +263,8 @@ "type": ["null", "string"] } }, - "type": ["null", "object"] + "type": ["null", "object"], + "additionalProperties": true }, "type": ["null", "array"] }, diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/refund_receipts.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/refund_receipts.json index e7271b4955c4..2f333006aa61 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/refund_receipts.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/refund_receipts.json @@ -38,6 +38,11 @@ "Line": { "items": { "properties": { + "SubTotalLineDetail": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": {} + }, "Id": { "type": ["null", "string"] }, @@ -84,7 +89,8 @@ "type": ["null", "object"] } }, - "type": ["null", "object"] + "type": ["null", "object"], + "additionalProperties": true }, "type": ["null", "array"] }, diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/sales_receipts.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/sales_receipts.json index b9ec030fbd03..e48e7e0a34f4 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/sales_receipts.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/schemas/sales_receipts.json @@ -116,7 +116,13 @@ "type": ["null", "array"], "items": { "type": ["null", "object"], + "additionalProperties": true, "properties": { + "SubTotalLineDetail": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": {} + }, "DiscountLineDetail": { "type": ["null", "object"], "properties": { diff --git a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/spec.json b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/spec.json index ead3ac5eddd6..bfb6a3669cf2 100644 --- a/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/spec.json +++ b/airbyte-integrations/connectors/source-quickbooks/source_quickbooks/spec.json @@ -46,7 +46,7 @@ "airbyte_secret": true }, "access_token": { - "description": "Access token fot making authenticated requests.", + "description": "Access token for making authenticated requests.", "title": "Access Token", "type": "string", "airbyte_secret": true diff --git a/docs/integrations/sources/quickbooks.md b/docs/integrations/sources/quickbooks.md index 48866deba5bc..8e74d5a6081f 100644 --- a/docs/integrations/sources/quickbooks.md +++ b/docs/integrations/sources/quickbooks.md @@ -105,6 +105,7 @@ This Source is capable of syncing the following [Streams](https://developer.intu | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------- | +| `3.0.2` | 2024-02-20 | [32236](https://github.com/airbytehq/airbyte/pull/32236) | Small typo in spec correction | | `3.0.1` | 2023-11-06 | [32236](https://github.com/airbytehq/airbyte/pull/32236) | Upgrade to `airbyte-cdk>=0.52.10` to resolve refresh token issues | | `3.0.0` | 2023-09-26 | [30770](https://github.com/airbytehq/airbyte/pull/30770) | Update schema to use `number` instead of `integer` | | `2.0.5` | 2023-09-26 | [30766](https://github.com/airbytehq/airbyte/pull/30766) | Fix improperly named keyword argument | From c9ba9df7895df5858dee047b2555d408b37811f3 Mon Sep 17 00:00:00 2001 From: Rodi Reich Zilberman <867491+rodireich@users.noreply.github.com> Date: Wed, 21 Feb 2024 09:44:55 -0800 Subject: [PATCH 03/74] =?UTF-8?q?=F0=9F=90=9B=20Change=20null=20cursor=20v?= =?UTF-8?q?alue=20query=20to=20not=20use=20IIF=20sql=20function=20(#35405)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airbyte-integrations/connectors/source-mssql/metadata.yaml | 2 +- .../java/io/airbyte/integrations/source/mssql/MssqlSource.java | 2 +- docs/integrations/sources/mssql.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mssql/metadata.yaml b/airbyte-integrations/connectors/source-mssql/metadata.yaml index 31cdd78a8aaf..3538ca06207a 100644 --- a/airbyte-integrations/connectors/source-mssql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mssql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: b5ea17b1-f170-46dc-bc31-cc744ca984c1 - dockerImageTag: 3.7.0 + dockerImageTag: 3.7.1 dockerRepository: airbyte/source-mssql documentationUrl: https://docs.airbyte.com/integrations/sources/mssql githubIssueLabel: source-mssql diff --git a/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java b/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java index 1b9e6ec994af..27bd0876a5dc 100644 --- a/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java +++ b/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java @@ -108,7 +108,7 @@ public class MssqlSource extends AbstractJdbcSource implements Source """; public static final String NULL_CURSOR_VALUE_WITH_SCHEMA_QUERY = """ - SELECT CAST(IIF(EXISTS(SELECT TOP 1 1 FROM "%s"."%s" WHERE "%s" IS NULL), 1, 0) AS BIT) AS %s + SELECT CASE WHEN (SELECT TOP 1 1 FROM "%s"."%s" WHERE "%s" IS NULL)=1 then 1 else 0 end as %s """; public static final String DRIVER_CLASS = DatabaseDriver.MSSQLSERVER.getDriverClassName(); public static final String MSSQL_CDC_OFFSET = "mssql_cdc_offset"; diff --git a/docs/integrations/sources/mssql.md b/docs/integrations/sources/mssql.md index a63ecb8dea0b..3b1f397ced49 100644 --- a/docs/integrations/sources/mssql.md +++ b/docs/integrations/sources/mssql.md @@ -342,6 +342,7 @@ WHERE actor_definition_id ='b5ea17b1-f170-46dc-bc31-cc744ca984c1' AND (configura | Version | Date | Pull Request | Subject | |:--------|:-----------|:------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.7.1 | 2024-02-20 | [35405](https://github.com/airbytehq/airbyte/pull/35405) | Change query syntax to make it compatible with Azure Synapse. | | 3.7.0 | 2024-01-30 | [33311](https://github.com/airbytehq/airbyte/pull/33311) | Source mssql with checkpointing initial sync. | | 3.6.1 | 2024-01-26 | [34573](https://github.com/airbytehq/airbyte/pull/34573) | Adopt CDK v0.16.0. | | 3.6.0 | 2024-01-10 | [33700](https://github.com/airbytehq/airbyte/pull/33700) | Remove CDC config options for data_to_sync and snapshot isolation. | From 35c73b3f9813a2bce570e118e07240d4741e7551 Mon Sep 17 00:00:00 2001 From: "Roman Yermilov [GL]" <86300758+roman-yermilov-gl@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:14:00 +0100 Subject: [PATCH 04/74] Source Google Ads: rollback patch 500 Internal Server Error (#35493) --- .../integration_tests/expected_records.jsonl | 6 +++--- .../expected_records_click.jsonl | 15 ++++++--------- .../connectors/source-google-ads/metadata.yaml | 2 +- .../connectors/source-google-ads/pyproject.toml | 2 +- .../source_google_ads/google_ads.py | 14 ++------------ .../source_google_ads/streams.py | 14 ++------------ .../unit_tests/test_incremental_events_streams.py | 4 ++-- .../source-google-ads/unit_tests/test_source.py | 2 +- .../source-google-ads/unit_tests/test_streams.py | 2 +- docs/integrations/sources/google-ads.md | 1 + 10 files changed, 20 insertions(+), 42 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records.jsonl index 1b8961da0beb..c734ff62715b 100644 --- a/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records.jsonl @@ -46,9 +46,9 @@ {"stream": "custom_audience", "data": {"custom_audience.description": "", "custom_audience.name": "Airbyte", "custom_audience.id": 523469909, "custom_audience.members": ["member_type: KEYWORD\nkeyword: \"etl elt\"\n", "member_type: KEYWORD\nkeyword: \"cloud data management and analytics\"\n", "member_type: KEYWORD\nkeyword: \"data integration\"\n", "member_type: KEYWORD\nkeyword: \"big data analytics database\"\n", "member_type: KEYWORD\nkeyword: \"data\"\n", "member_type: KEYWORD\nkeyword: \"data sherid nada\"\n", "member_type: KEYWORD\nkeyword: \"airbyteforeveryone\"\n", "member_type: KEYWORD\nkeyword: \"Airbyte\"\n"], "custom_audience.resource_name": "customers/4651612872/customAudiences/523469909", "custom_audience.status": "ENABLED", "custom_audience.type": "AUTO"}, "emitted_at": 1704407775427} {"stream": "audience", "data": {"customer.id": 4651612872, "audience.description": "", "audience.dimensions": ["audience_segments {\n segments {\n custom_audience {\n custom_audience: \"customers/4651612872/customAudiences/523469909\"\n }\n }\n}\n"], "audience.exclusion_dimension": "", "audience.id": 47792633, "audience.name": "Audience name 1", "audience.resource_name": "customers/4651612872/audiences/47792633", "audience.status": "ENABLED"}, "emitted_at": 1704407775721} {"stream": "audience", "data": {"customer.id": 4651612872, "audience.description": "", "audience.dimensions": ["audience_segments {\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80276\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80279\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80520\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80530\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/92931\"\n }\n }\n}\n"], "audience.exclusion_dimension": "", "audience.id": 97300129, "audience.name": "Upgraded Audience 1", "audience.resource_name": "customers/4651612872/audiences/97300129", "audience.status": "ENABLED"}, "emitted_at": 1704407775723} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Arts & Entertainment", "user_interest.resource_name": "customers/4651612872/userInterests/3", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 3, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777549} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Computers & Electronics", "user_interest.resource_name": "customers/4651612872/userInterests/5", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 5, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777550} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Finance", "user_interest.resource_name": "customers/4651612872/userInterests/7", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 7, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777551} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Arts & Entertainment", "user_interest.resource_name": "customers/4651612872/userInterests/3", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 3, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777549} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Computers & Electronics", "user_interest.resource_name": "customers/4651612872/userInterests/5", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 5, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777550} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Finance", "user_interest.resource_name": "customers/4651612872/userInterests/7", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 7, "user_interest.user_interest_parent": ""}, "emitted_at": 1704407777551} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21585034471, "label.name": "edgao-example-label", "label.resource_name": "customers/4651612872/labels/21585034471", "label.status": "ENABLED", "label.text_label.background_color": "#E993EB", "label.text_label.description": "example label for edgao"}, "emitted_at": 1704407779851} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21902092838, "label.name": "Test Label", "label.resource_name": "customers/4651612872/labels/21902092838", "label.status": "ENABLED", "label.text_label.background_color": "#8BCBD2", "label.text_label.description": "Description to test label"}, "emitted_at": 1704407779852} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21906377810, "label.name": "Test Delete label customer", "label.resource_name": "customers/4651612872/labels/21906377810", "label.status": "ENABLED", "label.text_label.background_color": "#8266C9", "label.text_label.description": ""}, "emitted_at": 1704407779852} diff --git a/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records_click.jsonl b/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records_click.jsonl index b2f87d068ffa..62c6a529e5bc 100644 --- a/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records_click.jsonl +++ b/airbyte-integrations/connectors/source-google-ads/integration_tests/expected_records_click.jsonl @@ -1,8 +1,7 @@ {"stream": "ad_group_ad_legacy", "data": {"ad_group_ad.ad.legacy_responsive_display_ad.accent_color": "", "ad_group.id": 155311392438, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.time_zone": "America/Los_Angeles", "metrics.active_view_cpm": 0.0, "metrics.active_view_ctr": 0.0, "metrics.active_view_impressions": 0, "metrics.active_view_measurability": 0.0, "metrics.active_view_measurable_cost_micros": 0, "metrics.active_view_measurable_impressions": 0, "metrics.active_view_viewability": 0.0, "ad_group_ad.ad_group": "customers/4651612872/adGroups/155311392438", "ad_group.name": "Airbyte", "ad_group.status": "ENABLED", "segments.ad_network_type": "SEARCH", "ad_group_ad.ad_strength": "EXCELLENT", "ad_group_ad.ad.type": "RESPONSIVE_SEARCH_AD", "metrics.all_conversions_from_interactions_rate": 5.657287433333334, "metrics.all_conversions_value": 833.910118, "metrics.all_conversions": 169.718623, "ad_group_ad.ad.legacy_responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.added_by_google_ads": false, "metrics.average_cost": 5602666.666666667, "metrics.average_cpc": 5602666.666666667, "metrics.average_cpe": 0.0, "metrics.average_cpm": 1031165644.1717792, "metrics.average_cpv": 0.0, "metrics.average_page_views": 0.0, "metrics.average_time_on_site": 0.0, "ad_group.base_ad_group": "customers/4651612872/adGroups/155311392438", "campaign.base_campaign": "customers/4651612872/campaigns/20643300404", "metrics.bounce_rate": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.business_name": "", "ad_group_ad.ad.legacy_responsive_display_ad.call_to_action_text": "", "campaign.id": 20643300404, "campaign.name": "mm_search_brand", "campaign.status": "ENABLED", "metrics.clicks": 30, "ad_group_ad.policy_summary.approval_status": "APPROVED", "metrics.conversions_from_interactions_rate": 0.22079663333333333, "metrics.conversions_value": 662.3899, "metrics.conversions": 6.623899, "metrics.cost_micros": 168080000, "metrics.cost_per_all_conversions": 990345.0607185282, "metrics.cost_per_conversion": 25374783.039415307, "metrics.cost_per_current_model_attributed_conversion": 25374783.039415307, "ad_group_ad.ad.final_mobile_urls": [], "ad_group_ad.ad.final_urls": ["https://airbyte.com/"], "ad_group_ad.ad.tracking_url_template": "", "ad_group_ad.ad.url_custom_parameters": [], "metrics.cross_device_conversions": 1.0, "metrics.ctr": 0.18404907975460122, "metrics.current_model_attributed_conversions_value": 662.3899, "metrics.current_model_attributed_conversions": 6.623899, "segments.date": "2023-12-31", "segments.day_of_week": "SUNDAY", "ad_group_ad.ad.expanded_text_ad.description": "", "ad_group_ad.ad.text_ad.description1": "", "ad_group_ad.ad.text_ad.description2": "", "ad_group_ad.ad.device_preference": "UNSPECIFIED", "ad_group_ad.ad.display_url": "", "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "ad_group_ad.ad.legacy_responsive_display_ad.logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.marketing_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_marketing_image": "", "ad_group_ad.ad.expanded_dynamic_search_ad.description": "", "ad_group_ad.ad.expanded_text_ad.description2": "", "ad_group_ad.ad.expanded_text_ad.headline_part3": "", "customer.id": 4651612872, "ad_group_ad.ad.legacy_responsive_display_ad.format_setting": "UNSPECIFIED", "metrics.gmail_forwards": 0, "metrics.gmail_saves": 0, "metrics.gmail_secondary_clicks": 0, "ad_group_ad.ad.text_ad.headline": "", "ad_group_ad.ad.expanded_text_ad.headline_part1": "", "ad_group_ad.ad.expanded_text_ad.headline_part2": "", "ad_group_ad.ad.id": 676665180945, "ad_group_ad.ad.image_ad.image_url": "", "ad_group_ad.ad.image_ad.pixel_height": 0, "ad_group_ad.ad.image_ad.pixel_width": 0, "ad_group_ad.ad.image_ad.mime_type": "UNSPECIFIED", "ad_group_ad.ad.image_ad.name": "", "metrics.impressions": 163, "metrics.interaction_rate": 0.18404907975460122, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interactions": 30, "ad_group_ad.ad.legacy_responsive_display_ad.long_headline": "", "ad_group_ad.ad.legacy_responsive_display_ad.main_color": "", "segments.month": "2023-12-01", "ad_group_ad.ad.responsive_display_ad.accent_color": "", "ad_group_ad.ad.responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.responsive_display_ad.business_name": "", "ad_group_ad.ad.responsive_display_ad.call_to_action_text": "", "ad_group_ad.ad.responsive_display_ad.descriptions": [], "ad_group_ad.ad.responsive_display_ad.price_prefix": "", "ad_group_ad.ad.responsive_display_ad.promo_text": "", "ad_group_ad.ad.responsive_display_ad.format_setting": "UNSPECIFIED", "ad_group_ad.ad.responsive_display_ad.headlines": [], "ad_group_ad.ad.responsive_display_ad.logo_images": [], "ad_group_ad.ad.responsive_display_ad.square_logo_images": [], "ad_group_ad.ad.responsive_display_ad.long_headline": "", "ad_group_ad.ad.responsive_display_ad.main_color": "", "ad_group_ad.ad.responsive_display_ad.marketing_images": [], "ad_group_ad.ad.responsive_display_ad.square_marketing_images": [], "ad_group_ad.ad.responsive_display_ad.youtube_videos": [], "ad_group_ad.ad.expanded_text_ad.path1": "", "ad_group_ad.ad.expanded_text_ad.path2": "", "metrics.percent_new_visitors": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.price_prefix": "", "ad_group_ad.ad.legacy_responsive_display_ad.promo_text": "", "segments.quarter": "2023-10-01", "ad_group_ad.ad.responsive_search_ad.descriptions": ["text: \"The most comprehensive catalog of connectors, trusted by 40,000K engineers\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"A high-performing and scalable data integration platform with advanced features.\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Try Airbyte for free! Connect Any Data, Any User, & Any Application Effortlessly.\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Build custom connectors in 10 min with our no-code connector builder.\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.headlines": ["text: \"Airbyte\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"The only ETL tool you need\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Build ELT Pipelines In Minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"No code, ELT Tool\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Replicate Data in Minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Open Source Integration\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Try Airbyte Cloud Free\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Browse Our Catalog\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Trusted by over 40K Engineers\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"14 Day Free Trial\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"300+ off-the-shelf connectors\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"No-Code Connector Builder\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Get started in minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Extract, Load & Transform\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Streamlined Data Pipeline\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.path1": "", "ad_group_ad.ad.responsive_search_ad.path2": "", "ad_group_ad.ad.legacy_responsive_display_ad.short_headline": "", "ad_group_ad.status": "ENABLED", "ad_group_ad.ad.system_managed_resource_source": "UNSPECIFIED", "metrics.top_impression_percentage": 0.8834355828220859, "ad_group_ad.ad.app_ad.descriptions": [], "ad_group_ad.ad.app_ad.headlines": [], "ad_group_ad.ad.app_ad.html5_media_bundles": [], "ad_group_ad.ad.app_ad.images": [], "ad_group_ad.ad.app_ad.mandatory_ad_text": "", "ad_group_ad.ad.app_ad.youtube_videos": [], "metrics.value_per_all_conversions": 4.9134862353909154, "metrics.value_per_conversion": 100.0, "metrics.value_per_current_model_attributed_conversion": 100.0, "metrics.video_quartile_p100_rate": 0.0, "metrics.video_quartile_p25_rate": 0.0, "metrics.video_quartile_p50_rate": 0.0, "metrics.video_quartile_p75_rate": 0.0, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0, "segments.week": "2023-12-25", "segments.year": 2023}, "emitted_at": 1707926876037} {"stream": "ad_group_ad_legacy", "data": {"ad_group_ad.ad.legacy_responsive_display_ad.accent_color": "", "ad_group.id": 155311392438, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.time_zone": "America/Los_Angeles", "metrics.active_view_cpm": 0.0, "metrics.active_view_ctr": 0.0, "metrics.active_view_impressions": 0, "metrics.active_view_measurability": 0.0, "metrics.active_view_measurable_cost_micros": 0, "metrics.active_view_measurable_impressions": 0, "metrics.active_view_viewability": 0.0, "ad_group_ad.ad_group": "customers/4651612872/adGroups/155311392438", "ad_group.name": "Airbyte", "ad_group.status": "ENABLED", "segments.ad_network_type": "SEARCH", "ad_group_ad.ad_strength": "EXCELLENT", "ad_group_ad.ad.type": "RESPONSIVE_SEARCH_AD", "metrics.all_conversions_from_interactions_rate": 5.881101891891892, "metrics.all_conversions_value": 1404.284328, "metrics.all_conversions": 217.60077, "ad_group_ad.ad.legacy_responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.added_by_google_ads": false, "metrics.average_cost": 8890000.0, "metrics.average_cpc": 8890000.0, "metrics.average_cpe": 0.0, "metrics.average_cpm": 1279883268.4824903, "metrics.average_cpv": 0.0, "metrics.average_page_views": 0.0, "metrics.average_time_on_site": 0.0, "ad_group.base_ad_group": "customers/4651612872/adGroups/155311392438", "campaign.base_campaign": "customers/4651612872/campaigns/20643300404", "metrics.bounce_rate": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.business_name": "", "ad_group_ad.ad.legacy_responsive_display_ad.call_to_action_text": "", "campaign.id": 20643300404, "campaign.name": "mm_search_brand", "campaign.status": "ENABLED", "metrics.clicks": 37, "ad_group_ad.policy_summary.approval_status": "APPROVED", "metrics.conversions_from_interactions_rate": 0.4133928378378378, "metrics.conversions_value": 1184.5535, "metrics.conversions": 15.295535, "metrics.cost_micros": 328930000, "metrics.cost_per_all_conversions": 1511621.4892070463, "metrics.cost_per_conversion": 21504968.606851608, "metrics.cost_per_current_model_attributed_conversion": 21504968.606851608, "ad_group_ad.ad.final_mobile_urls": [], "ad_group_ad.ad.final_urls": ["https://airbyte.com/"], "ad_group_ad.ad.tracking_url_template": "", "ad_group_ad.ad.url_custom_parameters": [], "metrics.cross_device_conversions": 3.0, "metrics.ctr": 0.14396887159533073, "metrics.current_model_attributed_conversions_value": 1184.5535, "metrics.current_model_attributed_conversions": 15.295535, "segments.date": "2024-01-01", "segments.day_of_week": "MONDAY", "ad_group_ad.ad.expanded_text_ad.description": "", "ad_group_ad.ad.text_ad.description1": "", "ad_group_ad.ad.text_ad.description2": "", "ad_group_ad.ad.device_preference": "UNSPECIFIED", "ad_group_ad.ad.display_url": "", "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "ad_group_ad.ad.legacy_responsive_display_ad.logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.marketing_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_marketing_image": "", "ad_group_ad.ad.expanded_dynamic_search_ad.description": "", "ad_group_ad.ad.expanded_text_ad.description2": "", "ad_group_ad.ad.expanded_text_ad.headline_part3": "", "customer.id": 4651612872, "ad_group_ad.ad.legacy_responsive_display_ad.format_setting": "UNSPECIFIED", "metrics.gmail_forwards": 0, "metrics.gmail_saves": 0, "metrics.gmail_secondary_clicks": 0, "ad_group_ad.ad.text_ad.headline": "", "ad_group_ad.ad.expanded_text_ad.headline_part1": "", "ad_group_ad.ad.expanded_text_ad.headline_part2": "", "ad_group_ad.ad.id": 676665180945, "ad_group_ad.ad.image_ad.image_url": "", "ad_group_ad.ad.image_ad.pixel_height": 0, "ad_group_ad.ad.image_ad.pixel_width": 0, "ad_group_ad.ad.image_ad.mime_type": "UNSPECIFIED", "ad_group_ad.ad.image_ad.name": "", "metrics.impressions": 257, "metrics.interaction_rate": 0.14396887159533073, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interactions": 37, "ad_group_ad.ad.legacy_responsive_display_ad.long_headline": "", "ad_group_ad.ad.legacy_responsive_display_ad.main_color": "", "segments.month": "2024-01-01", "ad_group_ad.ad.responsive_display_ad.accent_color": "", "ad_group_ad.ad.responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.responsive_display_ad.business_name": "", "ad_group_ad.ad.responsive_display_ad.call_to_action_text": "", "ad_group_ad.ad.responsive_display_ad.descriptions": [], "ad_group_ad.ad.responsive_display_ad.price_prefix": "", "ad_group_ad.ad.responsive_display_ad.promo_text": "", "ad_group_ad.ad.responsive_display_ad.format_setting": "UNSPECIFIED", "ad_group_ad.ad.responsive_display_ad.headlines": [], "ad_group_ad.ad.responsive_display_ad.logo_images": [], "ad_group_ad.ad.responsive_display_ad.square_logo_images": [], "ad_group_ad.ad.responsive_display_ad.long_headline": "", "ad_group_ad.ad.responsive_display_ad.main_color": "", "ad_group_ad.ad.responsive_display_ad.marketing_images": [], "ad_group_ad.ad.responsive_display_ad.square_marketing_images": [], "ad_group_ad.ad.responsive_display_ad.youtube_videos": [], "ad_group_ad.ad.expanded_text_ad.path1": "", "ad_group_ad.ad.expanded_text_ad.path2": "", "metrics.percent_new_visitors": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.price_prefix": "", "ad_group_ad.ad.legacy_responsive_display_ad.promo_text": "", "segments.quarter": "2024-01-01", "ad_group_ad.ad.responsive_search_ad.descriptions": ["text: \"The most comprehensive catalog of connectors, trusted by 40,000K engineers\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"A high-performing and scalable data integration platform with advanced features.\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Try Airbyte for free! Connect Any Data, Any User, & Any Application Effortlessly.\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Build custom connectors in 10 min with our no-code connector builder.\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.headlines": ["text: \"Airbyte\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"The only ETL tool you need\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Build ELT Pipelines In Minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"No code, ELT Tool\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Replicate Data in Minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Open Source Integration\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Try Airbyte Cloud Free\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Browse Our Catalog\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Trusted by over 40K Engineers\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"14 Day Free Trial\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"300+ off-the-shelf connectors\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"No-Code Connector Builder\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Get started in minutes\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Extract, Load & Transform\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Streamlined Data Pipeline\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.path1": "", "ad_group_ad.ad.responsive_search_ad.path2": "", "ad_group_ad.ad.legacy_responsive_display_ad.short_headline": "", "ad_group_ad.status": "ENABLED", "ad_group_ad.ad.system_managed_resource_source": "UNSPECIFIED", "metrics.top_impression_percentage": 0.9688715953307393, "ad_group_ad.ad.app_ad.descriptions": [], "ad_group_ad.ad.app_ad.headlines": [], "ad_group_ad.ad.app_ad.html5_media_bundles": [], "ad_group_ad.ad.app_ad.images": [], "ad_group_ad.ad.app_ad.mandatory_ad_text": "", "ad_group_ad.ad.app_ad.youtube_videos": [], "metrics.value_per_all_conversions": 6.45348970042707, "metrics.value_per_conversion": 77.44439798934788, "metrics.value_per_current_model_attributed_conversion": 77.44439798934788, "metrics.video_quartile_p100_rate": 0.0, "metrics.video_quartile_p25_rate": 0.0, "metrics.video_quartile_p50_rate": 0.0, "metrics.video_quartile_p75_rate": 0.0, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0, "segments.week": "2024-01-01", "segments.year": 2024}, "emitted_at": 1707926876046} -{"stream": "ad_group_ad_legacy", "data": {"ad_group_ad.ad.legacy_responsive_display_ad.accent_color": "", "ad_group.id": 152406853857, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.time_zone": "America/Los_Angeles", "metrics.active_view_cpm": 0.0, "metrics.active_view_ctr": 0.0, "metrics.active_view_impressions": 0, "metrics.active_view_measurability": 0.0, "metrics.active_view_measurable_cost_micros": 0, "metrics.active_view_measurable_impressions": 0, "metrics.active_view_viewability": 0.0, "ad_group_ad.ad_group": "customers/4651612872/adGroups/152406853857", "ad_group.name": "Fivetran", "ad_group.status": "ENABLED", "segments.ad_network_type": "SEARCH", "ad_group_ad.ad_strength": "EXCELLENT", "ad_group_ad.ad.type": "RESPONSIVE_SEARCH_AD", "metrics.all_conversions_from_interactions_rate": 0.0, "metrics.all_conversions_value": 0.0, "metrics.all_conversions": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.added_by_google_ads": false, "metrics.average_cost": 0.0, "metrics.average_cpc": 0.0, "metrics.average_cpe": 0.0, "metrics.average_cpm": 0.0, "metrics.average_cpv": 0.0, "metrics.average_page_views": 0.0, "metrics.average_time_on_site": 0.0, "ad_group.base_ad_group": "customers/4651612872/adGroups/152406853857", "campaign.base_campaign": "customers/4651612872/campaigns/20655886237", "metrics.bounce_rate": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.business_name": "", "ad_group_ad.ad.legacy_responsive_display_ad.call_to_action_text": "", "campaign.id": 20655886237, "campaign.name": "mm_search_competitors", "campaign.status": "ENABLED", "metrics.clicks": 0, "ad_group_ad.policy_summary.approval_status": "APPROVED", "metrics.conversions_from_interactions_rate": 0.0, "metrics.conversions_value": 0.0, "metrics.conversions": 0.0, "metrics.cost_micros": 0, "metrics.cost_per_all_conversions": 0.0, "metrics.cost_per_conversion": 0.0, "metrics.cost_per_current_model_attributed_conversion": 0.0, "ad_group_ad.ad.final_mobile_urls": [], "ad_group_ad.ad.final_urls": ["https://airbyte.com/etl-tools/fivetran-alternative-airbyte"], "ad_group_ad.ad.tracking_url_template": "", "ad_group_ad.ad.url_custom_parameters": [], "metrics.cross_device_conversions": 0.0, "metrics.ctr": 0.0, "metrics.current_model_attributed_conversions_value": 0.0, "metrics.current_model_attributed_conversions": 0.0, "segments.date": "2024-01-02", "segments.day_of_week": "TUESDAY", "ad_group_ad.ad.expanded_text_ad.description": "", "ad_group_ad.ad.text_ad.description1": "", "ad_group_ad.ad.text_ad.description2": "", "ad_group_ad.ad.device_preference": "UNSPECIFIED", "ad_group_ad.ad.display_url": "", "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "ad_group_ad.ad.legacy_responsive_display_ad.logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_logo_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.marketing_image": "", "ad_group_ad.ad.legacy_responsive_display_ad.square_marketing_image": "", "ad_group_ad.ad.expanded_dynamic_search_ad.description": "", "ad_group_ad.ad.expanded_text_ad.description2": "", "ad_group_ad.ad.expanded_text_ad.headline_part3": "", "customer.id": 4651612872, "ad_group_ad.ad.legacy_responsive_display_ad.format_setting": "UNSPECIFIED", "metrics.gmail_forwards": 0, "metrics.gmail_saves": 0, "metrics.gmail_secondary_clicks": 0, "ad_group_ad.ad.text_ad.headline": "", "ad_group_ad.ad.expanded_text_ad.headline_part1": "", "ad_group_ad.ad.expanded_text_ad.headline_part2": "", "ad_group_ad.ad.id": 677024318384, "ad_group_ad.ad.image_ad.image_url": "", "ad_group_ad.ad.image_ad.pixel_height": 0, "ad_group_ad.ad.image_ad.pixel_width": 0, "ad_group_ad.ad.image_ad.mime_type": "UNSPECIFIED", "ad_group_ad.ad.image_ad.name": "", "metrics.impressions": 38, "metrics.interaction_rate": 0.0, "metrics.interaction_event_types": [], "metrics.interactions": 0, "ad_group_ad.ad.legacy_responsive_display_ad.long_headline": "", "ad_group_ad.ad.legacy_responsive_display_ad.main_color": "", "segments.month": "2024-01-01", "ad_group_ad.ad.responsive_display_ad.accent_color": "", "ad_group_ad.ad.responsive_display_ad.allow_flexible_color": false, "ad_group_ad.ad.responsive_display_ad.business_name": "", "ad_group_ad.ad.responsive_display_ad.call_to_action_text": "", "ad_group_ad.ad.responsive_display_ad.descriptions": [], "ad_group_ad.ad.responsive_display_ad.price_prefix": "", "ad_group_ad.ad.responsive_display_ad.promo_text": "", "ad_group_ad.ad.responsive_display_ad.format_setting": "UNSPECIFIED", "ad_group_ad.ad.responsive_display_ad.headlines": [], "ad_group_ad.ad.responsive_display_ad.logo_images": [], "ad_group_ad.ad.responsive_display_ad.square_logo_images": [], "ad_group_ad.ad.responsive_display_ad.long_headline": "", "ad_group_ad.ad.responsive_display_ad.main_color": "", "ad_group_ad.ad.responsive_display_ad.marketing_images": [], "ad_group_ad.ad.responsive_display_ad.square_marketing_images": [], "ad_group_ad.ad.responsive_display_ad.youtube_videos": [], "ad_group_ad.ad.expanded_text_ad.path1": "", "ad_group_ad.ad.expanded_text_ad.path2": "", "metrics.percent_new_visitors": 0.0, "ad_group_ad.ad.legacy_responsive_display_ad.price_prefix": "", "ad_group_ad.ad.legacy_responsive_display_ad.promo_text": "", "segments.quarter": "2024-01-01", "ad_group_ad.ad.responsive_search_ad.descriptions": ["text: \"Airbyte vs. Fivetran - Comparison | Pros & Cons (2023)\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Airbyte is an open-source data integration / ETL alternative to Fivetran\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Self-Service for Airbyte Cloud. Open-Source Edition Deployable in Minutes. Volume-Based\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Compare data sources and destinations, features, pricing and more.\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.headlines": ["text: \"Airbyte vs. Fivetran\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Fivetran Alternative\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Need a Fivetran alternative?\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Power Up Your Data Integration\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"ELT tool\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Open Source Data Integration\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Airbyte: Top Open-Source ELT\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Choose the Leading ELT tool\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"ELT Alternative?\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Looking for a Better ELT Tool?\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Automated ETL Pipeline\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Airbyte Connectors\"\nasset_performance_label: LOW\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Open-Source ELT Tool\"\nasset_performance_label: GOOD\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Hundreds of connectors\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n", "text: \"Streamlined Data Pipeline\"\nasset_performance_label: LEARNING\npolicy_summary_info {\n review_status: REVIEWED\n approval_status: APPROVED\n}\n"], "ad_group_ad.ad.responsive_search_ad.path1": "", "ad_group_ad.ad.responsive_search_ad.path2": "", "ad_group_ad.ad.legacy_responsive_display_ad.short_headline": "", "ad_group_ad.status": "ENABLED", "ad_group_ad.ad.system_managed_resource_source": "UNSPECIFIED", "metrics.top_impression_percentage": 0.9736842105263158, "ad_group_ad.ad.app_ad.descriptions": [], "ad_group_ad.ad.app_ad.headlines": [], "ad_group_ad.ad.app_ad.html5_media_bundles": [], "ad_group_ad.ad.app_ad.images": [], "ad_group_ad.ad.app_ad.mandatory_ad_text": "", "ad_group_ad.ad.app_ad.youtube_videos": [], "metrics.value_per_all_conversions": 0.0, "metrics.value_per_conversion": 0.0, "metrics.value_per_current_model_attributed_conversion": 0.0, "metrics.video_quartile_p100_rate": 0.0, "metrics.video_quartile_p25_rate": 0.0, "metrics.video_quartile_p50_rate": 0.0, "metrics.video_quartile_p75_rate": 0.0, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0, "segments.week": "2024-01-01", "segments.year": 2024}, "emitted_at": 1707926876055} -{"stream": "campaign_budget", "data": {"customer.id": 4651612872, "campaign.id": 20643300404, "campaign_budget.aligned_bidding_strategy_id": 0, "campaign_budget.amount_micros": 330000000, "campaign_budget.delivery_method": "STANDARD", "campaign_budget.explicitly_shared": false, "campaign_budget.has_recommended_budget": false, "campaign_budget.id": 13022493317, "campaign_budget.name": "mm_search_brand", "campaign_budget.period": "DAILY", "campaign_budget.recommended_budget_amount_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_clicks": 0, "campaign_budget.recommended_budget_estimated_change_weekly_cost_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_interactions": 0, "campaign_budget.recommended_budget_estimated_change_weekly_views": 0, "campaign_budget.reference_count": 1, "campaign_budget.resource_name": "customers/4651612872/campaignBudgets/13022493317", "campaign_budget.status": "ENABLED", "campaign_budget.total_amount_micros": 0, "campaign_budget.type": "STANDARD", "segments.date": "2023-12-31", "segments.budget_campaign_association_status.campaign": "customers/4651612872/campaigns/20643300404", "segments.budget_campaign_association_status.status": "ENABLED", "metrics.all_conversions": 148.017621, "metrics.all_conversions_from_interactions_rate": 4.9339207, "metrics.all_conversions_value": 803.783622, "metrics.average_cost": 5602666.666666667, "metrics.average_cpc": 5602666.666666667, "metrics.average_cpe": 0.0, "metrics.average_cpm": 1031165644.1717792, "metrics.average_cpv": 0.0, "metrics.clicks": 30, "metrics.conversions": 6.623899, "metrics.conversions_from_interactions_rate": 0.22079663333333333, "metrics.conversions_value": 662.3899, "metrics.cost_micros": 168080000, "metrics.cost_per_all_conversions": 1135540.4773057392, "metrics.cost_per_conversion": 25374783.039415307, "metrics.cross_device_conversions": 0.0, "metrics.ctr": 0.18404907975460122, "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "metrics.impressions": 163, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interaction_rate": 0.18404907975460122, "metrics.interactions": 30, "metrics.value_per_all_conversions": 5.430323880154783, "metrics.value_per_conversion": 100.0, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0}, "emitted_at": 1705322166925} -{"stream": "campaign_budget", "data": {"customer.id": 4651612872, "campaign.id": 20643300404, "campaign_budget.aligned_bidding_strategy_id": 0, "campaign_budget.amount_micros": 330000000, "campaign_budget.delivery_method": "STANDARD", "campaign_budget.explicitly_shared": false, "campaign_budget.has_recommended_budget": false, "campaign_budget.id": 13022493317, "campaign_budget.name": "mm_search_brand", "campaign_budget.period": "DAILY", "campaign_budget.recommended_budget_amount_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_clicks": 0, "campaign_budget.recommended_budget_estimated_change_weekly_cost_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_interactions": 0, "campaign_budget.recommended_budget_estimated_change_weekly_views": 0, "campaign_budget.reference_count": 1, "campaign_budget.resource_name": "customers/4651612872/campaignBudgets/13022493317", "campaign_budget.status": "ENABLED", "campaign_budget.total_amount_micros": 0, "campaign_budget.type": "STANDARD", "segments.date": "2024-01-01", "segments.budget_campaign_association_status.campaign": "customers/4651612872/campaigns/20643300404", "segments.budget_campaign_association_status.status": "ENABLED", "metrics.all_conversions": 189.791889, "metrics.all_conversions_from_interactions_rate": 5.129510513513513, "metrics.all_conversions_value": 1315.049854, "metrics.average_cost": 8890000.0, "metrics.average_cpc": 8890000.0, "metrics.average_cpe": 0.0, "metrics.average_cpm": 1279883268.4824903, "metrics.average_cpv": 0.0, "metrics.clicks": 37, "metrics.conversions": 13.295535, "metrics.conversions_from_interactions_rate": 0.35933878378378376, "metrics.conversions_value": 1129.5535, "metrics.cost_micros": 328930000, "metrics.cost_per_all_conversions": 1733108.8369113603, "metrics.cost_per_conversion": 24739884.480015285, "metrics.cross_device_conversions": 3.0, "metrics.ctr": 0.14396887159533073, "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "metrics.impressions": 257, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interaction_rate": 0.14396887159533073, "metrics.interactions": 37, "metrics.value_per_all_conversions": 6.928904395909143, "metrics.value_per_conversion": 84.9573559845467, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0}, "emitted_at": 1705322166935} +{"stream": "campaign_budget", "data": {"customer.id": 4651612872, "campaign.id": 20643300404, "campaign_budget.aligned_bidding_strategy_id": 0, "campaign_budget.amount_micros": 150000000, "campaign_budget.delivery_method": "STANDARD", "campaign_budget.explicitly_shared": false, "campaign_budget.has_recommended_budget": false, "campaign_budget.id": 13022493317, "campaign_budget.name": "mm_search_brand", "campaign_budget.period": "DAILY", "campaign_budget.recommended_budget_amount_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_clicks": 0, "campaign_budget.recommended_budget_estimated_change_weekly_cost_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_views": 0, "campaign_budget.reference_count": 1, "campaign_budget.resource_name": "customers/4651612872/campaignBudgets/13022493317", "campaign_budget.status": "ENABLED", "campaign_budget.total_amount_micros": 0, "campaign_budget.type": "STANDARD", "segments.date": "2023-12-31", "segments.budget_campaign_association_status.campaign": "customers/4651612872/campaigns/20643300404", "segments.budget_campaign_association_status.status": "ENABLED", "metrics.average_cost": 5602666.666666667, "metrics.average_cpc": 5602666.666666667, "metrics.average_cpe": 0.0, "metrics.average_cpm": 1031165644.1717792, "metrics.average_cpv": 0.0, "metrics.clicks": 30, "metrics.cost_micros": 168080000, "metrics.ctr": 0.18404907975460122, "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "metrics.impressions": 163, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interaction_rate": 0.18404907975460122, "metrics.interactions": 30, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0}, "emitted_at": 1705322166925} +{"stream": "campaign_budget", "data": {"customer.id": 4651612872, "campaign.id": 20643300404, "campaign_budget.aligned_bidding_strategy_id": 0, "campaign_budget.amount_micros": 150000000, "campaign_budget.delivery_method": "STANDARD", "campaign_budget.explicitly_shared": false, "campaign_budget.has_recommended_budget": false, "campaign_budget.id": 13022493317, "campaign_budget.name": "mm_search_brand", "campaign_budget.period": "DAILY", "campaign_budget.recommended_budget_amount_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_clicks": 0, "campaign_budget.recommended_budget_estimated_change_weekly_cost_micros": 0, "campaign_budget.recommended_budget_estimated_change_weekly_views": 0, "campaign_budget.reference_count": 1, "campaign_budget.resource_name": "customers/4651612872/campaignBudgets/13022493317", "campaign_budget.status": "ENABLED", "campaign_budget.total_amount_micros": 0, "campaign_budget.type": "STANDARD", "segments.date": "2024-01-02", "segments.budget_campaign_association_status.campaign": "customers/4651612872/campaigns/20643300404", "segments.budget_campaign_association_status.status": "ENABLED", "metrics.average_cost": 2976862.745098039, "metrics.average_cpc": 2976862.745098039, "metrics.average_cpe": 0.0, "metrics.average_cpm": 780565552.6992288, "metrics.average_cpv": 0.0, "metrics.clicks": 102, "metrics.cost_micros": 303640000, "metrics.ctr": 0.2622107969151671, "metrics.engagement_rate": 0.0, "metrics.engagements": 0, "metrics.impressions": 389, "metrics.interaction_event_types": ["InteractionEventType.CLICK"], "metrics.interaction_rate": 0.2622107969151671, "metrics.interactions": 102, "metrics.video_view_rate": 0.0, "metrics.video_views": 0, "metrics.view_through_conversions": 0}, "emitted_at": 1705322166925} {"stream": "ad_group_custom", "data": {"ad_group.targeting_setting.target_restrictions": ["targeting_dimension: AGE_RANGE\nbid_only: true\n", "targeting_dimension: GENDER\nbid_only: true\n", "targeting_dimension: PARENTAL_STATUS\nbid_only: true\n", "targeting_dimension: INCOME_RANGE\nbid_only: true\n"], "segments.date": "2024-01-03"}, "emitted_at": 1704408105935} {"stream": "ad_group_custom", "data": {"ad_group.targeting_setting.target_restrictions": ["targeting_dimension: AGE_RANGE\nbid_only: true\n", "targeting_dimension: GENDER\nbid_only: true\n", "targeting_dimension: PARENTAL_STATUS\nbid_only: true\n", "targeting_dimension: INCOME_RANGE\nbid_only: true\n", "targeting_dimension: TOPIC\nbid_only: true\n"], "segments.date": "2024-01-03"}, "emitted_at": 1704408105942} {"stream": "ad_group_custom", "data": {"ad_group.targeting_setting.target_restrictions": ["targeting_dimension: AUDIENCE\nbid_only: true\n", "targeting_dimension: AGE_RANGE\nbid_only: true\n", "targeting_dimension: GENDER\nbid_only: true\n", "targeting_dimension: PARENTAL_STATUS\nbid_only: true\n", "targeting_dimension: INCOME_RANGE\nbid_only: true\n"], "segments.date": "2024-01-02"}, "emitted_at": 1704408105943} @@ -26,9 +25,7 @@ {"stream": "customer", "data": {"customer.auto_tagging_enabled": true, "customer.call_reporting_setting.call_conversion_action": "customers/4651612872/conversionActions/179", "customer.call_reporting_setting.call_conversion_reporting_enabled": true, "customer.call_reporting_setting.call_reporting_enabled": true, "customer.conversion_tracking_setting.conversion_tracking_id": 657981234, "customer.conversion_tracking_setting.cross_account_conversion_tracking_id": 0, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.final_url_suffix": "", "customer.has_partners_badge": false, "customer.id": 4651612872, "customer.manager": false, "customer.optimization_score": 0.7609283000000001, "customer.optimization_score_weight": 3182.4700060000005, "customer.pay_per_conversion_eligibility_failure_reasons": [], "customer.remarketing_setting.google_global_site_tag": "\n\n\n", "customer.resource_name": "customers/4651612872", "customer.test_account": false, "customer.time_zone": "America/Los_Angeles", "customer.tracking_url_template": "{lpurl}?utm_term={keyword}&utm_campaign={_utmcampaign}&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam={campaignid}&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3", "segments.date": "2023-12-31"}, "emitted_at": 1704408117407} {"stream": "customer", "data": {"customer.auto_tagging_enabled": true, "customer.call_reporting_setting.call_conversion_action": "customers/4651612872/conversionActions/179", "customer.call_reporting_setting.call_conversion_reporting_enabled": true, "customer.call_reporting_setting.call_reporting_enabled": true, "customer.conversion_tracking_setting.conversion_tracking_id": 657981234, "customer.conversion_tracking_setting.cross_account_conversion_tracking_id": 0, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.final_url_suffix": "", "customer.has_partners_badge": false, "customer.id": 4651612872, "customer.manager": false, "customer.optimization_score": 0.7609283000000001, "customer.optimization_score_weight": 3182.4700060000005, "customer.pay_per_conversion_eligibility_failure_reasons": [], "customer.remarketing_setting.google_global_site_tag": "\n\n\n", "customer.resource_name": "customers/4651612872", "customer.test_account": false, "customer.time_zone": "America/Los_Angeles", "customer.tracking_url_template": "{lpurl}?utm_term={keyword}&utm_campaign={_utmcampaign}&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam={campaignid}&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3", "segments.date": "2024-01-01"}, "emitted_at": 1704408117408} {"stream": "customer", "data": {"customer.auto_tagging_enabled": true, "customer.call_reporting_setting.call_conversion_action": "customers/4651612872/conversionActions/179", "customer.call_reporting_setting.call_conversion_reporting_enabled": true, "customer.call_reporting_setting.call_reporting_enabled": true, "customer.conversion_tracking_setting.conversion_tracking_id": 657981234, "customer.conversion_tracking_setting.cross_account_conversion_tracking_id": 0, "customer.currency_code": "USD", "customer.descriptive_name": "Airbyte", "customer.final_url_suffix": "", "customer.has_partners_badge": false, "customer.id": 4651612872, "customer.manager": false, "customer.optimization_score": 0.7609283000000001, "customer.optimization_score_weight": 3182.4700060000005, "customer.pay_per_conversion_eligibility_failure_reasons": [], "customer.remarketing_setting.google_global_site_tag": "\n\n\n", "customer.resource_name": "customers/4651612872", "customer.test_account": false, "customer.time_zone": "America/Los_Angeles", "customer.tracking_url_template": "{lpurl}?utm_term={keyword}&utm_campaign={_utmcampaign}&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam={campaignid}&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3", "segments.date": "2024-01-02"}, "emitted_at": 1704408117408} -{"stream":"campaign","data":{"campaign.accessible_bidding_strategy":"","campaign.ad_serving_optimization_status":"OPTIMIZE","campaign.advertising_channel_sub_type":"UNSPECIFIED","campaign.advertising_channel_type":"SEARCH","campaign.app_campaign_setting.app_id":"","campaign.app_campaign_setting.app_store":"UNSPECIFIED","campaign.app_campaign_setting.bidding_strategy_goal_type":"UNSPECIFIED","campaign.base_campaign":"customers/4651612872/campaigns/20643300404","campaign.bidding_strategy":"","campaign.bidding_strategy_type":"MAXIMIZE_CONVERSIONS","campaign.campaign_budget":"customers/4651612872/campaignBudgets/13022493317","campaign_budget.amount_micros":330000000,"campaign.commission.commission_rate_micros":0,"campaign.dynamic_search_ads_setting.domain_name":"","campaign.dynamic_search_ads_setting.feeds":[],"campaign.dynamic_search_ads_setting.language_code":"","campaign.dynamic_search_ads_setting.use_supplied_urls_only":false,"campaign.end_date":"2037-12-30","campaign.excluded_parent_asset_field_types":[],"campaign.experiment_type":"BASE","campaign.final_url_suffix":"","campaign.frequency_caps":[],"campaign.geo_target_type_setting.negative_geo_target_type":"PRESENCE","campaign.geo_target_type_setting.positive_geo_target_type":"PRESENCE_OR_INTEREST","campaign.hotel_setting.hotel_center_id":0,"campaign.id":20643300404,"campaign.labels":[],"campaign.local_campaign_setting.location_source_type":"UNSPECIFIED","campaign.manual_cpc.enhanced_cpc_enabled":false,"campaign.manual_cpm":"","campaign.manual_cpv":"","campaign.maximize_conversion_value.target_roas":0.0,"campaign.maximize_conversions.target_cpa_micros":0,"campaign.name":"mm_search_brand","campaign.network_settings.target_content_network":false,"campaign.network_settings.target_google_search":true,"campaign.network_settings.target_partner_search_network":false,"campaign.network_settings.target_search_network":false,"campaign.optimization_goal_setting.optimization_goal_types":[],"campaign.optimization_score":0.7188557564030126,"campaign.payment_mode":"CLICKS","campaign.percent_cpc.cpc_bid_ceiling_micros":0,"campaign.percent_cpc.enhanced_cpc_enabled":false,"campaign.real_time_bidding_setting.opt_in":false,"campaign.resource_name":"customers/4651612872/campaigns/20643300404","campaign.selective_optimization.conversion_actions":[],"campaign.serving_status":"SERVING","campaign.shopping_setting.campaign_priority":0,"campaign.shopping_setting.enable_local":false,"campaign.shopping_setting.merchant_id":0,"campaign.start_date":"2023-10-10","campaign.status":"ENABLED","campaign.target_cpa.cpc_bid_ceiling_micros":0,"campaign.target_cpa.cpc_bid_floor_micros":0,"campaign.target_cpa.target_cpa_micros":0,"campaign.target_cpm.target_frequency_goal.target_count":0,"campaign.target_cpm.target_frequency_goal.time_unit":"UNSPECIFIED","campaign.target_impression_share.cpc_bid_ceiling_micros":0,"campaign.target_impression_share.location":"UNSPECIFIED","campaign.target_impression_share.location_fraction_micros":0,"campaign.target_roas.cpc_bid_ceiling_micros":0,"campaign.target_roas.cpc_bid_floor_micros":0,"campaign.target_roas.target_roas":0.0,"campaign.target_spend.cpc_bid_ceiling_micros":0,"campaign.target_spend.target_spend_micros":0,"campaign.targeting_setting.target_restrictions":["targeting_dimension: AUDIENCE\nbid_only: true\n"],"campaign.tracking_setting.tracking_url":"","campaign.tracking_url_template":"{lpurl}?utm_term={keyword}&utm_campaign=mm_search_brand&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam=20643300404&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3","campaign.url_custom_parameters":[],"campaign.vanity_pharma.vanity_pharma_display_url_mode":"UNSPECIFIED","campaign.vanity_pharma.vanity_pharma_text":"UNSPECIFIED","campaign.video_brand_safety_suitability":"UNSPECIFIED","metrics.clicks":1,"metrics.ctr":0.3333333333333333,"metrics.conversions":0.0,"metrics.conversions_value":0.0,"metrics.cost_micros":2980000,"metrics.impressions":3,"metrics.video_views":0,"metrics.video_quartile_p100_rate":0.0,"metrics.active_view_cpm":0.0,"metrics.active_view_ctr":0.0,"metrics.active_view_impressions":0,"metrics.active_view_measurability":0.0,"metrics.active_view_measurable_cost_micros":0,"metrics.active_view_measurable_impressions":0,"metrics.active_view_viewability":0.0,"metrics.average_cost":2980000.0,"metrics.average_cpc":2980000.0,"metrics.average_cpm":993333333.3333334,"metrics.interactions":1,"metrics.interaction_event_types":["InteractionEventType.CLICK"],"metrics.value_per_conversion":0.0,"metrics.cost_per_conversion":0.0,"segments.date":"2023-12-31","segments.hour":0,"segments.ad_network_type":"SEARCH"},"emitted_at":1707481305175} -{"stream":"campaign","data":{"campaign.accessible_bidding_strategy":"","campaign.ad_serving_optimization_status":"OPTIMIZE","campaign.advertising_channel_sub_type":"UNSPECIFIED","campaign.advertising_channel_type":"SEARCH","campaign.app_campaign_setting.app_id":"","campaign.app_campaign_setting.app_store":"UNSPECIFIED","campaign.app_campaign_setting.bidding_strategy_goal_type":"UNSPECIFIED","campaign.base_campaign":"customers/4651612872/campaigns/20643300404","campaign.bidding_strategy":"","campaign.bidding_strategy_type":"MAXIMIZE_CONVERSIONS","campaign.campaign_budget":"customers/4651612872/campaignBudgets/13022493317","campaign_budget.amount_micros":330000000,"campaign.commission.commission_rate_micros":0,"campaign.dynamic_search_ads_setting.domain_name":"","campaign.dynamic_search_ads_setting.feeds":[],"campaign.dynamic_search_ads_setting.language_code":"","campaign.dynamic_search_ads_setting.use_supplied_urls_only":false,"campaign.end_date":"2037-12-30","campaign.excluded_parent_asset_field_types":[],"campaign.experiment_type":"BASE","campaign.final_url_suffix":"","campaign.frequency_caps":[],"campaign.geo_target_type_setting.negative_geo_target_type":"PRESENCE","campaign.geo_target_type_setting.positive_geo_target_type":"PRESENCE_OR_INTEREST","campaign.hotel_setting.hotel_center_id":0,"campaign.id":20643300404,"campaign.labels":[],"campaign.local_campaign_setting.location_source_type":"UNSPECIFIED","campaign.manual_cpc.enhanced_cpc_enabled":false,"campaign.manual_cpm":"","campaign.manual_cpv":"","campaign.maximize_conversion_value.target_roas":0.0,"campaign.maximize_conversions.target_cpa_micros":0,"campaign.name":"mm_search_brand","campaign.network_settings.target_content_network":false,"campaign.network_settings.target_google_search":true,"campaign.network_settings.target_partner_search_network":false,"campaign.network_settings.target_search_network":false,"campaign.optimization_goal_setting.optimization_goal_types":[],"campaign.optimization_score":0.7188557564030126,"campaign.payment_mode":"CLICKS","campaign.percent_cpc.cpc_bid_ceiling_micros":0,"campaign.percent_cpc.enhanced_cpc_enabled":false,"campaign.real_time_bidding_setting.opt_in":false,"campaign.resource_name":"customers/4651612872/campaigns/20643300404","campaign.selective_optimization.conversion_actions":[],"campaign.serving_status":"SERVING","campaign.shopping_setting.campaign_priority":0,"campaign.shopping_setting.enable_local":false,"campaign.shopping_setting.merchant_id":0,"campaign.start_date":"2023-10-10","campaign.status":"ENABLED","campaign.target_cpa.cpc_bid_ceiling_micros":0,"campaign.target_cpa.cpc_bid_floor_micros":0,"campaign.target_cpa.target_cpa_micros":0,"campaign.target_cpm.target_frequency_goal.target_count":0,"campaign.target_cpm.target_frequency_goal.time_unit":"UNSPECIFIED","campaign.target_impression_share.cpc_bid_ceiling_micros":0,"campaign.target_impression_share.location":"UNSPECIFIED","campaign.target_impression_share.location_fraction_micros":0,"campaign.target_roas.cpc_bid_ceiling_micros":0,"campaign.target_roas.cpc_bid_floor_micros":0,"campaign.target_roas.target_roas":0.0,"campaign.target_spend.cpc_bid_ceiling_micros":0,"campaign.target_spend.target_spend_micros":0,"campaign.targeting_setting.target_restrictions":["targeting_dimension: AUDIENCE\nbid_only: true\n"],"campaign.tracking_setting.tracking_url":"","campaign.tracking_url_template":"{lpurl}?utm_term={keyword}&utm_campaign=mm_search_brand&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam=20643300404&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3","campaign.url_custom_parameters":[],"campaign.vanity_pharma.vanity_pharma_display_url_mode":"UNSPECIFIED","campaign.vanity_pharma.vanity_pharma_text":"UNSPECIFIED","campaign.video_brand_safety_suitability":"UNSPECIFIED","metrics.clicks":0,"metrics.ctr":0.0,"metrics.conversions":0.0,"metrics.conversions_value":0.0,"metrics.cost_micros":0,"metrics.impressions":2,"metrics.video_views":0,"metrics.video_quartile_p100_rate":0.0,"metrics.active_view_cpm":0.0,"metrics.active_view_ctr":0.0,"metrics.active_view_impressions":0,"metrics.active_view_measurability":0.0,"metrics.active_view_measurable_cost_micros":0,"metrics.active_view_measurable_impressions":0,"metrics.active_view_viewability":0.0,"metrics.average_cost":0.0,"metrics.average_cpc":0.0,"metrics.average_cpm":0.0,"metrics.interactions":0,"metrics.interaction_event_types":[],"metrics.value_per_conversion":0.0,"metrics.cost_per_conversion":0.0,"segments.date":"2023-12-31","segments.hour":3,"segments.ad_network_type":"SEARCH"},"emitted_at":1707481305182} -{"stream":"campaign","data":{"campaign.accessible_bidding_strategy":"","campaign.ad_serving_optimization_status":"OPTIMIZE","campaign.advertising_channel_sub_type":"UNSPECIFIED","campaign.advertising_channel_type":"SEARCH","campaign.app_campaign_setting.app_id":"","campaign.app_campaign_setting.app_store":"UNSPECIFIED","campaign.app_campaign_setting.bidding_strategy_goal_type":"UNSPECIFIED","campaign.base_campaign":"customers/4651612872/campaigns/20643300404","campaign.bidding_strategy":"","campaign.bidding_strategy_type":"MAXIMIZE_CONVERSIONS","campaign.campaign_budget":"customers/4651612872/campaignBudgets/13022493317","campaign_budget.amount_micros":330000000,"campaign.commission.commission_rate_micros":0,"campaign.dynamic_search_ads_setting.domain_name":"","campaign.dynamic_search_ads_setting.feeds":[],"campaign.dynamic_search_ads_setting.language_code":"","campaign.dynamic_search_ads_setting.use_supplied_urls_only":false,"campaign.end_date":"2037-12-30","campaign.excluded_parent_asset_field_types":[],"campaign.experiment_type":"BASE","campaign.final_url_suffix":"","campaign.frequency_caps":[],"campaign.geo_target_type_setting.negative_geo_target_type":"PRESENCE","campaign.geo_target_type_setting.positive_geo_target_type":"PRESENCE_OR_INTEREST","campaign.hotel_setting.hotel_center_id":0,"campaign.id":20643300404,"campaign.labels":[],"campaign.local_campaign_setting.location_source_type":"UNSPECIFIED","campaign.manual_cpc.enhanced_cpc_enabled":false,"campaign.manual_cpm":"","campaign.manual_cpv":"","campaign.maximize_conversion_value.target_roas":0.0,"campaign.maximize_conversions.target_cpa_micros":0,"campaign.name":"mm_search_brand","campaign.network_settings.target_content_network":false,"campaign.network_settings.target_google_search":true,"campaign.network_settings.target_partner_search_network":false,"campaign.network_settings.target_search_network":false,"campaign.optimization_goal_setting.optimization_goal_types":[],"campaign.optimization_score":0.7188557564030126,"campaign.payment_mode":"CLICKS","campaign.percent_cpc.cpc_bid_ceiling_micros":0,"campaign.percent_cpc.enhanced_cpc_enabled":false,"campaign.real_time_bidding_setting.opt_in":false,"campaign.resource_name":"customers/4651612872/campaigns/20643300404","campaign.selective_optimization.conversion_actions":[],"campaign.serving_status":"SERVING","campaign.shopping_setting.campaign_priority":0,"campaign.shopping_setting.enable_local":false,"campaign.shopping_setting.merchant_id":0,"campaign.start_date":"2023-10-10","campaign.status":"ENABLED","campaign.target_cpa.cpc_bid_ceiling_micros":0,"campaign.target_cpa.cpc_bid_floor_micros":0,"campaign.target_cpa.target_cpa_micros":0,"campaign.target_cpm.target_frequency_goal.target_count":0,"campaign.target_cpm.target_frequency_goal.time_unit":"UNSPECIFIED","campaign.target_impression_share.cpc_bid_ceiling_micros":0,"campaign.target_impression_share.location":"UNSPECIFIED","campaign.target_impression_share.location_fraction_micros":0,"campaign.target_roas.cpc_bid_ceiling_micros":0,"campaign.target_roas.cpc_bid_floor_micros":0,"campaign.target_roas.target_roas":0.0,"campaign.target_spend.cpc_bid_ceiling_micros":0,"campaign.target_spend.target_spend_micros":0,"campaign.targeting_setting.target_restrictions":["targeting_dimension: AUDIENCE\nbid_only: true\n"],"campaign.tracking_setting.tracking_url":"","campaign.tracking_url_template":"{lpurl}?utm_term={keyword}&utm_campaign=mm_search_brand&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam=20643300404&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3","campaign.url_custom_parameters":[],"campaign.vanity_pharma.vanity_pharma_display_url_mode":"UNSPECIFIED","campaign.vanity_pharma.vanity_pharma_text":"UNSPECIFIED","campaign.video_brand_safety_suitability":"UNSPECIFIED","metrics.clicks":2,"metrics.ctr":0.5,"metrics.conversions":0.0,"metrics.conversions_value":0.0,"metrics.cost_micros":1180000,"metrics.impressions":4,"metrics.video_views":0,"metrics.video_quartile_p100_rate":0.0,"metrics.active_view_cpm":0.0,"metrics.active_view_ctr":0.0,"metrics.active_view_impressions":0,"metrics.active_view_measurability":0.0,"metrics.active_view_measurable_cost_micros":0,"metrics.active_view_measurable_impressions":0,"metrics.active_view_viewability":0.0,"metrics.average_cost":590000.0,"metrics.average_cpc":590000.0,"metrics.average_cpm":295000000.0,"metrics.interactions":2,"metrics.interaction_event_types":["InteractionEventType.CLICK"],"metrics.value_per_conversion":0.0,"metrics.cost_per_conversion":0.0,"segments.date":"2023-12-31","segments.hour":5,"segments.ad_network_type":"SEARCH"},"emitted_at":1707481305189} +{"stream": "campaign", "data": {"campaign.accessible_bidding_strategy": "", "campaign.ad_serving_optimization_status": "OPTIMIZE", "campaign.advertising_channel_sub_type": "UNSPECIFIED", "campaign.advertising_channel_type": "SEARCH", "campaign.app_campaign_setting.app_id": "", "campaign.app_campaign_setting.app_store": "UNSPECIFIED", "campaign.app_campaign_setting.bidding_strategy_goal_type": "UNSPECIFIED", "campaign.base_campaign": "customers/4651612872/campaigns/20643300404", "campaign.bidding_strategy": "", "campaign.bidding_strategy_type": "MAXIMIZE_CONVERSIONS", "campaign.campaign_budget": "customers/4651612872/campaignBudgets/13022493317", "campaign_budget.amount_micros": 150000000, "campaign.commission.commission_rate_micros": 0, "campaign.dynamic_search_ads_setting.domain_name": "", "campaign.dynamic_search_ads_setting.feeds": [], "campaign.dynamic_search_ads_setting.language_code": "", "campaign.dynamic_search_ads_setting.use_supplied_urls_only": false, "campaign.end_date": "2037-12-30", "campaign.excluded_parent_asset_field_types": [], "campaign.experiment_type": "BASE", "campaign.final_url_suffix": "", "campaign.frequency_caps": [], "campaign.geo_target_type_setting.negative_geo_target_type": "PRESENCE", "campaign.geo_target_type_setting.positive_geo_target_type": "PRESENCE_OR_INTEREST", "campaign.hotel_setting.hotel_center_id": 0, "campaign.id": 20643300404, "campaign.labels": [], "campaign.local_campaign_setting.location_source_type": "UNSPECIFIED", "campaign.manual_cpc.enhanced_cpc_enabled": false, "campaign.manual_cpm": "", "campaign.manual_cpv": "", "campaign.maximize_conversion_value.target_roas": 0.0, "campaign.maximize_conversions.target_cpa_micros": 0, "campaign.name": "mm_search_brand", "campaign.network_settings.target_content_network": false, "campaign.network_settings.target_google_search": true, "campaign.network_settings.target_partner_search_network": false, "campaign.network_settings.target_search_network": false, "campaign.optimization_goal_setting.optimization_goal_types": [], "campaign.optimization_score": 0.5967968177178755, "campaign.payment_mode": "CLICKS", "campaign.percent_cpc.cpc_bid_ceiling_micros": 0, "campaign.percent_cpc.enhanced_cpc_enabled": false, "campaign.real_time_bidding_setting.opt_in": false, "campaign.resource_name": "customers/4651612872/campaigns/20643300404", "campaign.selective_optimization.conversion_actions": [], "campaign.serving_status": "SERVING", "campaign.shopping_setting.campaign_priority": 0, "campaign.shopping_setting.enable_local": false, "campaign.shopping_setting.merchant_id": 0, "campaign.start_date": "2023-10-10", "campaign.status": "ENABLED", "campaign.target_cpa.cpc_bid_ceiling_micros": 0, "campaign.target_cpa.cpc_bid_floor_micros": 0, "campaign.target_cpa.target_cpa_micros": 0, "campaign.target_cpm.target_frequency_goal.target_count": 0, "campaign.target_cpm.target_frequency_goal.time_unit": "UNSPECIFIED", "campaign.target_impression_share.cpc_bid_ceiling_micros": 0, "campaign.target_impression_share.location": "UNSPECIFIED", "campaign.target_impression_share.location_fraction_micros": 0, "campaign.target_roas.cpc_bid_ceiling_micros": 0, "campaign.target_roas.cpc_bid_floor_micros": 0, "campaign.target_roas.target_roas": 0.0, "campaign.target_spend.cpc_bid_ceiling_micros": 0, "campaign.target_spend.target_spend_micros": 0, "campaign.targeting_setting.target_restrictions": ["targeting_dimension: AUDIENCE\nbid_only: true\n"], "campaign.tracking_setting.tracking_url": "", "campaign.tracking_url_template": "{lpurl}?utm_term={keyword}&utm_campaign=mm_search_brand&utm_source=adwords&utm_medium=ppc&hsa_acc=4651612872&hsa_cam=20643300404&hsa_grp={adgroupid}&hsa_ad={creative}&hsa_src={network}&hsa_tgt={targetid}&hsa_kw={keyword}&hsa_mt={matchtype}&hsa_net=adwords&hsa_ver=3", "campaign.url_custom_parameters": [], "campaign.vanity_pharma.vanity_pharma_display_url_mode": "UNSPECIFIED", "campaign.vanity_pharma.vanity_pharma_text": "UNSPECIFIED", "campaign.video_brand_safety_suitability": "UNSPECIFIED", "metrics.clicks": 0, "metrics.ctr": 0.0, "metrics.conversions": 0.0, "metrics.conversions_value": 0.0, "metrics.cost_micros": 0, "metrics.impressions": 2, "metrics.video_views": 0, "metrics.video_quartile_p100_rate": 0.0, "metrics.active_view_cpm": 0.0, "metrics.active_view_ctr": 0.0, "metrics.active_view_impressions": 0, "metrics.active_view_measurability": 0.0, "metrics.active_view_measurable_cost_micros": 0, "metrics.active_view_measurable_impressions": 0, "metrics.active_view_viewability": 0.0, "metrics.average_cost": 0.0, "metrics.average_cpc": 0.0, "metrics.average_cpm": 0.0, "metrics.interactions": 0, "metrics.interaction_event_types": [], "metrics.value_per_conversion": 0.0, "metrics.cost_per_conversion": 0.0, "segments.date": "2023-12-31", "segments.hour": 3, "segments.ad_network_type": "SEARCH"}, "emitted_at": 1708533414290} {"stream": "campaign_label", "data": {"campaign.id": 12124071339, "label.id": 21585034471, "campaign.resource_name": "customers/4651612872/campaigns/12124071339", "campaign_label.resource_name": "customers/4651612872/campaignLabels/12124071339~21585034471", "label.name": "edgao-example-label", "label.resource_name": "customers/4651612872/labels/21585034471"}, "emitted_at": 1704408119170} {"stream": "campaign_label", "data": {"campaign.id": 13284356762, "label.id": 21585034471, "campaign.resource_name": "customers/4651612872/campaigns/13284356762", "campaign_label.resource_name": "customers/4651612872/campaignLabels/13284356762~21585034471", "label.name": "edgao-example-label", "label.resource_name": "customers/4651612872/labels/21585034471"}, "emitted_at": 1704408119172} {"stream": "campaign_label", "data": {"campaign.id": 16820250687, "label.id": 21906377810, "campaign.resource_name": "customers/4651612872/campaigns/16820250687", "campaign_label.resource_name": "customers/4651612872/campaignLabels/16820250687~21906377810", "label.name": "Test Delete label customer", "label.resource_name": "customers/4651612872/labels/21906377810"}, "emitted_at": 1704408119173} @@ -45,9 +42,9 @@ {"stream": "custom_audience", "data": {"custom_audience.description": "", "custom_audience.name": "Airbyte", "custom_audience.id": 523469909, "custom_audience.members": ["member_type: KEYWORD\nkeyword: \"etl elt\"\n", "member_type: KEYWORD\nkeyword: \"cloud data management and analytics\"\n", "member_type: KEYWORD\nkeyword: \"data integration\"\n", "member_type: KEYWORD\nkeyword: \"big data analytics database\"\n", "member_type: KEYWORD\nkeyword: \"data\"\n", "member_type: KEYWORD\nkeyword: \"data sherid nada\"\n", "member_type: KEYWORD\nkeyword: \"airbyteforeveryone\"\n", "member_type: KEYWORD\nkeyword: \"Airbyte\"\n"], "custom_audience.resource_name": "customers/4651612872/customAudiences/523469909", "custom_audience.status": "ENABLED", "custom_audience.type": "AUTO"}, "emitted_at": 1704408121936} {"stream": "audience", "data": {"customer.id": 4651612872, "audience.description": "", "audience.dimensions": ["audience_segments {\n segments {\n custom_audience {\n custom_audience: \"customers/4651612872/customAudiences/523469909\"\n }\n }\n}\n"], "audience.exclusion_dimension": "", "audience.id": 47792633, "audience.name": "Audience name 1", "audience.resource_name": "customers/4651612872/audiences/47792633", "audience.status": "ENABLED"}, "emitted_at": 1704408122314} {"stream": "audience", "data": {"customer.id": 4651612872, "audience.description": "", "audience.dimensions": ["audience_segments {\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80276\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80279\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80520\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/80530\"\n }\n }\n segments {\n user_interest {\n user_interest_category: \"customers/4651612872/userInterests/92931\"\n }\n }\n}\n"], "audience.exclusion_dimension": "", "audience.id": 97300129, "audience.name": "Upgraded Audience 1", "audience.resource_name": "customers/4651612872/audiences/97300129", "audience.status": "ENABLED"}, "emitted_at": 1704408122315} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Arts & Entertainment", "user_interest.resource_name": "customers/4651612872/userInterests/3", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 3, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124247} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Computers & Electronics", "user_interest.resource_name": "customers/4651612872/userInterests/5", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 5, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124249} -{"stream": "user_interest", "data": {"user_interest.availabilities": null, "user_interest.launched_to_all": null, "user_interest.name": "Finance", "user_interest.resource_name": "customers/4651612872/userInterests/7", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 7, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124250} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Arts & Entertainment", "user_interest.resource_name": "customers/4651612872/userInterests/3", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 3, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124247} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Computers & Electronics", "user_interest.resource_name": "customers/4651612872/userInterests/5", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 5, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124249} +{"stream": "user_interest", "data": {"user_interest.availabilities": [], "user_interest.launched_to_all": true, "user_interest.name": "Finance", "user_interest.resource_name": "customers/4651612872/userInterests/7", "user_interest.taxonomy_type": "VERTICAL_GEO", "user_interest.user_interest_id": 7, "user_interest.user_interest_parent": ""}, "emitted_at": 1704408124250} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21585034471, "label.name": "edgao-example-label", "label.resource_name": "customers/4651612872/labels/21585034471", "label.status": "ENABLED", "label.text_label.background_color": "#E993EB", "label.text_label.description": "example label for edgao"}, "emitted_at": 1704408126496} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21902092838, "label.name": "Test Label", "label.resource_name": "customers/4651612872/labels/21902092838", "label.status": "ENABLED", "label.text_label.background_color": "#8BCBD2", "label.text_label.description": "Description to test label"}, "emitted_at": 1704408126498} {"stream": "label", "data": {"customer.id": 4651612872, "label.id": 21906377810, "label.name": "Test Delete label customer", "label.resource_name": "customers/4651612872/labels/21906377810", "label.status": "ENABLED", "label.text_label.background_color": "#8266C9", "label.text_label.description": ""}, "emitted_at": 1704408126499} diff --git a/airbyte-integrations/connectors/source-google-ads/metadata.yaml b/airbyte-integrations/connectors/source-google-ads/metadata.yaml index dbb331aee581..ed883a5080af 100644 --- a/airbyte-integrations/connectors/source-google-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-ads/metadata.yaml @@ -11,7 +11,7 @@ data: connectorSubtype: api connectorType: source definitionId: 253487c0-2246-43ba-a21f-5116b20a2c50 - dockerImageTag: 3.3.3 + dockerImageTag: 3.3.4 dockerRepository: airbyte/source-google-ads documentationUrl: https://docs.airbyte.com/integrations/sources/google-ads githubIssueLabel: source-google-ads diff --git a/airbyte-integrations/connectors/source-google-ads/pyproject.toml b/airbyte-integrations/connectors/source-google-ads/pyproject.toml index f548977790e5..0535b4fa62d9 100644 --- a/airbyte-integrations/connectors/source-google-ads/pyproject.toml +++ b/airbyte-integrations/connectors/source-google-ads/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "3.3.2" +version = "3.3.4" name = "source-google-ads" description = "Source implementation for Google Ads." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-google-ads/source_google_ads/google_ads.py b/airbyte-integrations/connectors/source-google-ads/source_google_ads/google_ads.py index 9ef7b00d9c94..09ebafcd9267 100644 --- a/airbyte-integrations/connectors/source-google-ads/source_google_ads/google_ads.py +++ b/airbyte-integrations/connectors/source-google-ads/source_google_ads/google_ads.py @@ -214,18 +214,8 @@ def get_field_value(field_value: GoogleAdsRow, field: str, schema_type: Mapping[ return field_value @staticmethod - def parse_single_result(schema: Mapping[str, Any], result: GoogleAdsRow, nullable: Optional[List[str]] = None): - if nullable is None: - nullable = [] + def parse_single_result(schema: Mapping[str, Any], result: GoogleAdsRow): props = schema.get("properties") fields = GoogleAds.get_fields_from_schema(schema) - # Making fields nullable is a temporary try to avoid `500 Internal server error` happen when - # `user_interest.availabilities` and `user_interest.launched_to_all` fields are queried while syncing `user_interest` stream. - # It seems like the values for the fields have changed following the 500 errors and it is unexpected, - # so until we understand the issue with the 500 errors, we will nullify those two fields. - # This should affect only the `user_interest` stream. - # TODO: we need to get rid of the nullable condition once the issue https://github.com/airbytehq/oncall/issues/4306 to be resolved. - single_record = { - field: GoogleAds.get_field_value(result, field, props.get(field)) if field not in nullable else None for field in fields - } + single_record = {field: GoogleAds.get_field_value(result, field, props.get(field)) for field in fields} return single_record diff --git a/airbyte-integrations/connectors/source-google-ads/source_google_ads/streams.py b/airbyte-integrations/connectors/source-google-ads/source_google_ads/streams.py index d47a0362587d..499bceca367e 100644 --- a/airbyte-integrations/connectors/source-google-ads/source_google_ads/streams.py +++ b/airbyte-integrations/connectors/source-google-ads/source_google_ads/streams.py @@ -31,24 +31,14 @@ def __init__(self, api: GoogleAds, customers: List[CustomerModel]): self.customers = customers def get_query(self, stream_slice: Mapping[str, Any]) -> str: - # The following construction excludes "user_interest.availabilities" and "user_interest.launched_to_all" fields - # from the query because they are a cause of "500 Internal server error" on the google side. - # The oncall issue: https://github.com/airbytehq/oncall/issues/4306 - # TODO: replace with fields = GoogleAds.get_fields_from_schema(self.get_json_schema()) - fields = [ - field - for field in GoogleAds.get_fields_from_schema(self.get_json_schema()) - if not (field == "user_interest.availabilities" or field == "user_interest.launched_to_all") - ] + fields = GoogleAds.get_fields_from_schema(self.get_json_schema()) table_name = get_resource_name(self.name) query = GoogleAds.convert_schema_into_query(fields=fields, table_name=table_name) return query def parse_response(self, response: SearchPager, stream_slice: Optional[Mapping[str, Any]] = None) -> Iterable[Mapping]: for result in response: - yield self.google_ads_client.parse_single_result( - self.get_json_schema(), result, nullable=["user_interest.availabilities", "user_interest.launched_to_all"] - ) + yield self.google_ads_client.parse_single_result(self.get_json_schema(), result) def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, any]]]: for customer in self.customers: diff --git a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_incremental_events_streams.py b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_incremental_events_streams.py index 67933ba65e48..8ddf8bd80fba 100644 --- a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_incremental_events_streams.py +++ b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_incremental_events_streams.py @@ -51,7 +51,7 @@ def mock_response_child(): class MockGoogleAds(GoogleAds): - def parse_single_result(self, schema, result, nullable = None): + def parse_single_result(self, schema, result): return result def send_request(self, query: str, customer_id: str, login_customer_id: str = "default"): @@ -219,7 +219,7 @@ def mock_response_4(): class MockGoogleAdsLimit(GoogleAds): count = 0 - def parse_single_result(self, schema, result, nullable = None): + def parse_single_result(self, schema, result): return result def send_request(self, query: str, customer_id: str, login_customer_id: str = "default"): diff --git a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_source.py b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_source.py index 26db52663a91..6394817edd99 100644 --- a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_source.py @@ -507,7 +507,7 @@ def test_get_customers(mocker, customer_status_filter, expected_ids, send_reques mock_google_api.get_accessible_accounts.return_value = ["123", "789"] mock_google_api.send_request.side_effect = mock_send_request - mock_google_api.parse_single_result.side_effect = lambda schema, result, nullable: result + mock_google_api.parse_single_result.side_effect = lambda schema, result: result mock_config = {"customer_status_filter": customer_status_filter, "customer_ids": ["123", "456", "789"]} diff --git a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py index a03e1a3511cc..a171b869d3d2 100644 --- a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py @@ -48,7 +48,7 @@ def mock_response_2(): class MockGoogleAds(GoogleAds): count = 0 - def parse_single_result(self, schema, result, nullable = None): + def parse_single_result(self, schema, result): return result def send_request(self, query: str, customer_id: str, login_customer_id: str = "none"): diff --git a/docs/integrations/sources/google-ads.md b/docs/integrations/sources/google-ads.md index c4fa5e68c852..703474a83533 100644 --- a/docs/integrations/sources/google-ads.md +++ b/docs/integrations/sources/google-ads.md @@ -280,6 +280,7 @@ Due to a limitation in the Google Ads API which does not allow getting performan | Version | Date | Pull Request | Subject | |:---------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------| +| `3.3.4` | 2024-02-21 | [35493](https://github.com/airbytehq/airbyte/pull/35493) | Rolling back the patch 3.3.3 made for `user_interest` steam | | `3.3.3` | 2024-02-14 | [35280](https://github.com/airbytehq/airbyte/pull/35280) | Temporary patch that disables some fields to avoid 500 error when syncing `user_interest` steam | | `3.3.2` | 2024-02-12 | [35158](https://github.com/airbytehq/airbyte/pull/35158) | Manage dependencies with Poetry. | | `3.3.1` | 2024-01-16 | [34007](https://github.com/airbytehq/airbyte/pull/34007) | prepare for airbyte-lib | From 602d3ce063f43dd678ed0c882e84c4e68f0f7c81 Mon Sep 17 00:00:00 2001 From: Alex Birdsall Date: Wed, 21 Feb 2024 11:32:34 -0800 Subject: [PATCH 05/74] Fix syntax error in `tools/bin/manage.sh`, used to publish airbyte cdk (#35466) --- tools/integrations/manage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/integrations/manage.sh b/tools/integrations/manage.sh index c90a47c36c88..1133e356cccb 100755 --- a/tools/integrations/manage.sh +++ b/tools/integrations/manage.sh @@ -191,7 +191,7 @@ cmd_publish() { _error_if_tag_exists "$versioned_image" # building the connector - if [ "$path" != "airbyte-cdk/python"] + if [ "$path" != "airbyte-cdk/python" ]; then # The python CDK will already have been built and tested earlier in the github workflow. cmd_build "$path" "$run_tests" fi From 911cee423f8334361cf954d96fd102c604b5929e Mon Sep 17 00:00:00 2001 From: Akash Kulkarni <113392464+akashkulk@users.noreply.github.com> Date: Wed, 21 Feb 2024 12:49:57 -0800 Subject: [PATCH 06/74] [DB sources] : Reduce CDC state compression limit to 1MB (#35511) --- airbyte-cdk/java/airbyte-cdk/README.md | 1 + .../core/src/main/resources/version.properties | 2 +- .../internals/AirbyteSchemaHistoryStorage.java | 2 +- .../internals/AirbyteSchemaHistoryStorageTest.java | 12 ++++++------ ...than_3_mb.dat => dbhistory_greater_than_1_mb.dat} | 0 ...ss_than_3_mb.dat => dbhistory_less_than_1_mb.dat} | 0 6 files changed, 9 insertions(+), 8 deletions(-) rename airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/{dbhistory_greater_than_3_mb.dat => dbhistory_greater_than_1_mb.dat} (100%) rename airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/{dbhistory_less_than_3_mb.dat => dbhistory_less_than_1_mb.dat} (100%) diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index c3c8979e897b..3fb31042d45d 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -166,6 +166,7 @@ MavenLocal debugging steps: | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Add Junit progress information to the test logs | | 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | | 0.21.2 | 2024-02-20 | [\#34978](https://github.com/airbytehq/airbyte/pull/34978) | Reduce log noise in NormalizationLogParser. | | 0.21.1 | 2024-02-20 | [\#35199](https://github.com/airbytehq/airbyte/pull/35199) | Add thread names to the logs. | diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties index 177f844ea34a..955936a54212 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties @@ -1 +1 @@ -version=0.21.3 +version=0.21.4 diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorage.java b/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorage.java index d64a3eed2b0e..a3525cc0a3c8 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorage.java +++ b/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorage.java @@ -39,7 +39,7 @@ public class AirbyteSchemaHistoryStorage { private static final Logger LOGGER = LoggerFactory.getLogger(AirbyteSchemaHistoryStorage.class); - private static final long SIZE_LIMIT_TO_COMPRESS_MB = 3; + private static final long SIZE_LIMIT_TO_COMPRESS_MB = 1; public static final int ONE_MB = 1024 * 1024; private static final Charset UTF8 = StandardCharsets.UTF_8; diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorageTest.java b/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorageTest.java index 268c11a6012e..482936bd54aa 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorageTest.java +++ b/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/java/io/airbyte/cdk/integrations/debezium/internals/AirbyteSchemaHistoryStorageTest.java @@ -19,8 +19,8 @@ public class AirbyteSchemaHistoryStorageTest { @Test - public void testForContentBiggerThan3MBLimit() throws IOException { - final String contentReadDirectlyFromFile = MoreResources.readResource("dbhistory_greater_than_3_mb.dat"); + public void testForContentBiggerThan1MBLimit() throws IOException { + final String contentReadDirectlyFromFile = MoreResources.readResource("dbhistory_greater_than_1_mb.dat"); final AirbyteSchemaHistoryStorage schemaHistoryStorageFromUncompressedContent = AirbyteSchemaHistoryStorage.initializeDBHistory( new SchemaHistory<>(Optional.of(Jsons.jsonNode(contentReadDirectlyFromFile)), @@ -46,14 +46,14 @@ public void testForContentBiggerThan3MBLimit() throws IOException { @Test public void sizeTest() throws IOException { assertEquals(5.881045341491699, - AirbyteSchemaHistoryStorage.calculateSizeOfStringInMB(MoreResources.readResource("dbhistory_greater_than_3_mb.dat"))); + AirbyteSchemaHistoryStorage.calculateSizeOfStringInMB(MoreResources.readResource("dbhistory_greater_than_1_mb.dat"))); assertEquals(0.0038671493530273438, - AirbyteSchemaHistoryStorage.calculateSizeOfStringInMB(MoreResources.readResource("dbhistory_less_than_3_mb.dat"))); + AirbyteSchemaHistoryStorage.calculateSizeOfStringInMB(MoreResources.readResource("dbhistory_less_than_1_mb.dat"))); } @Test - public void testForContentLessThan3MBLimit() throws IOException { - final String contentReadDirectlyFromFile = MoreResources.readResource("dbhistory_less_than_3_mb.dat"); + public void testForContentLessThan1MBLimit() throws IOException { + final String contentReadDirectlyFromFile = MoreResources.readResource("dbhistory_less_than_1_mb.dat"); final AirbyteSchemaHistoryStorage schemaHistoryStorageFromUncompressedContent = AirbyteSchemaHistoryStorage.initializeDBHistory( new SchemaHistory<>(Optional.of(Jsons.jsonNode(contentReadDirectlyFromFile)), diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_greater_than_3_mb.dat b/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_greater_than_1_mb.dat similarity index 100% rename from airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_greater_than_3_mb.dat rename to airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_greater_than_1_mb.dat diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_less_than_3_mb.dat b/airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_less_than_1_mb.dat similarity index 100% rename from airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_less_than_3_mb.dat rename to airbyte-cdk/java/airbyte-cdk/db-sources/src/test/resources/dbhistory_less_than_1_mb.dat From c9b7d8acb2a856791ace77c9faed19c806370196 Mon Sep 17 00:00:00 2001 From: ambirdsall Date: Wed, 21 Feb 2024 21:49:35 +0000 Subject: [PATCH 07/74] =?UTF-8?q?=F0=9F=A4=96=20Bump=20patch=20version=20o?= =?UTF-8?q?f=20Python=20CDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airbyte-cdk/python/.bumpversion.cfg | 2 +- airbyte-cdk/python/CHANGELOG.md | 3 +++ airbyte-cdk/python/Dockerfile | 4 ++-- airbyte-cdk/python/setup.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/airbyte-cdk/python/.bumpversion.cfg b/airbyte-cdk/python/.bumpversion.cfg index a1f0725409dc..3998909aab1d 100644 --- a/airbyte-cdk/python/.bumpversion.cfg +++ b/airbyte-cdk/python/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.64.0 +current_version = 0.64.1 commit = False [bumpversion:file:setup.py] diff --git a/airbyte-cdk/python/CHANGELOG.md b/airbyte-cdk/python/CHANGELOG.md index 62616a3086c9..d2c8909afc43 100644 --- a/airbyte-cdk/python/CHANGELOG.md +++ b/airbyte-cdk/python/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.64.1 + + ## 0.64.0 Low-code: Add filter to RemoveFields diff --git a/airbyte-cdk/python/Dockerfile b/airbyte-cdk/python/Dockerfile index 6df448cb5535..9fe635147342 100644 --- a/airbyte-cdk/python/Dockerfile +++ b/airbyte-cdk/python/Dockerfile @@ -10,7 +10,7 @@ RUN apk --no-cache upgrade \ && apk --no-cache add tzdata build-base # install airbyte-cdk -RUN pip install --prefix=/install airbyte-cdk==0.64.0 +RUN pip install --prefix=/install airbyte-cdk==0.64.1 # build a clean environment FROM base @@ -32,5 +32,5 @@ ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] # needs to be the same as CDK -LABEL io.airbyte.version=0.64.0 +LABEL io.airbyte.version=0.64.1 LABEL io.airbyte.name=airbyte/source-declarative-manifest diff --git a/airbyte-cdk/python/setup.py b/airbyte-cdk/python/setup.py index 86036db6b3ee..604e30a2bc0f 100644 --- a/airbyte-cdk/python/setup.py +++ b/airbyte-cdk/python/setup.py @@ -36,7 +36,7 @@ name="airbyte-cdk", # The version of the airbyte-cdk package is used at runtime to validate manifests. That validation must be # updated if our semver format changes such as using release candidate versions. - version="0.64.0", + version="0.64.1", description="A framework for writing Airbyte Connectors.", long_description=README, long_description_content_type="text/markdown", From 5724ca0cf07f259fc0e23e198895478eae5da75a Mon Sep 17 00:00:00 2001 From: Alexandre Girard Date: Wed, 21 Feb 2024 14:14:37 -0800 Subject: [PATCH 08/74] Add ignore_stream_slicer_parameters_on_paginated_requests flag (#35462) --- .../declarative_component_schema.yaml | 4 ++ .../models/declarative_component_schema.py | 4 ++ .../parsers/model_to_component_factory.py | 9 ++++- .../retrievers/simple_retriever.py | 13 +++--- .../retrievers/test_simple_retriever.py | 40 +++++++++++++++++++ 5 files changed, 63 insertions(+), 7 deletions(-) diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml index 50d6db7da017..4a5165ca8e7e 100644 --- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml +++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml @@ -2001,6 +2001,10 @@ definitions: anyOf: - "$ref": "#/definitions/DefaultPaginator" - "$ref": "#/definitions/NoPagination" + ignore_stream_slicer_parameters_on_paginated_requests: + description: If true, the partition router and incremental request options will be ignored when paginating requests. Request options set directly on the requester will not be ignored. + type: boolean + default: false partition_router: title: Partition Router description: PartitionRouter component that describes how to partition the stream, enabling incremental syncs and checkpointing. diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py index 78006147385f..1ddc137356aa 100644 --- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py +++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py @@ -1338,6 +1338,10 @@ class SimpleRetriever(BaseModel): None, description="Paginator component that describes how to navigate through the API's pages.", ) + ignore_stream_slicer_parameters_on_paginated_requests: Optional[bool] = Field( + False, + description='If true, the partition router and incremental request options will be ignored when paginating requests. Request options set directly on the requester will not be ignored.', + ) partition_router: Optional[ Union[ CustomPartitionRouter, diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py index d9f4930d7bdf..380435c06a4e 100644 --- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py @@ -958,12 +958,17 @@ def create_simple_retriever( cursor_used_for_stop_condition = cursor if stop_condition_on_cursor else None paginator = ( self._create_component_from_model( - model=model.paginator, config=config, url_base=url_base, cursor_used_for_stop_condition=cursor_used_for_stop_condition + model=model.paginator, + config=config, + url_base=url_base, + cursor_used_for_stop_condition=cursor_used_for_stop_condition, ) if model.paginator else NoPagination(parameters={}) ) + ignore_stream_slicer_parameters_on_paginated_requests = model.ignore_stream_slicer_parameters_on_paginated_requests or False + if self._limit_slices_fetched or self._emit_connector_builder_messages: return SimpleRetrieverTestReadDecorator( name=name, @@ -975,6 +980,7 @@ def create_simple_retriever( cursor=cursor, config=config, maximum_number_of_slices=self._limit_slices_fetched or 5, + ignore_stream_slicer_parameters_on_paginated_requests=ignore_stream_slicer_parameters_on_paginated_requests, parameters=model.parameters or {}, ) return SimpleRetriever( @@ -986,6 +992,7 @@ def create_simple_retriever( stream_slicer=stream_slicer, cursor=cursor, config=config, + ignore_stream_slicer_parameters_on_paginated_requests=ignore_stream_slicer_parameters_on_paginated_requests, parameters=model.parameters or {}, ) diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py index 549a694fd059..a9c946044922 100644 --- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py @@ -59,6 +59,7 @@ class SimpleRetriever(Retriever): paginator: Optional[Paginator] = None stream_slicer: StreamSlicer = SinglePartitionRouter(parameters={}) cursor: Optional[Cursor] = None + ignore_stream_slicer_parameters_on_paginated_requests: bool = False def __post_init__(self, parameters: Mapping[str, Any]) -> None: self._paginator = self.paginator or NoPagination(parameters=parameters) @@ -105,12 +106,12 @@ def _get_request_options( Returned merged mapping otherwise """ # FIXME we should eventually remove the usage of stream_state as part of the interpolation - return combine_mappings( - [ - paginator_method(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token), - stream_slicer_method(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token), - ] - ) + mappings = [ + paginator_method(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token), + ] + if not next_page_token or not self.ignore_stream_slicer_parameters_on_paginated_requests: + mappings.append(stream_slicer_method(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)) + return combine_mappings(mappings) def _request_headers( self, diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/retrievers/test_simple_retriever.py b/airbyte-cdk/python/unit_tests/sources/declarative/retrievers/test_simple_retriever.py index 1747c8ec4d07..438a1497df84 100644 --- a/airbyte-cdk/python/unit_tests/sources/declarative/retrievers/test_simple_retriever.py +++ b/airbyte-cdk/python/unit_tests/sources/declarative/retrievers/test_simple_retriever.py @@ -273,6 +273,46 @@ def test_get_request_headers(test_name, paginator_mapping, expected_mapping): pass +@pytest.mark.parametrize( + "test_name, paginator_mapping, ignore_stream_slicer_parameters_on_paginated_requests, next_page_token, expected_mapping", + [ + ("test_do_not_ignore_stream_slicer_params_if_ignore_is_true_but_no_next_page_token", {"key_from_pagination": "1000"}, True, None, {"key_from_pagination": "1000"}), + ("test_do_not_ignore_stream_slicer_params_if_ignore_is_false_and_no_next_page_token", {"key_from_pagination": "1000"}, False, None, {"key_from_pagination": "1000", "key_from_slicer": "value"}), + ("test_ignore_stream_slicer_params_on_paginated_request", {"key_from_pagination": "1000"}, True, {"page": 2}, {"key_from_pagination": "1000"}), + ("test_do_not_ignore_stream_slicer_params_on_paginated_request", {"key_from_pagination": "1000"}, False, {"page": 2}, {"key_from_pagination": "1000", "key_from_slicer": "value"}), + ], +) +def test_ignore_stream_slicer_parameters_on_paginated_requests(test_name, paginator_mapping, ignore_stream_slicer_parameters_on_paginated_requests, next_page_token, expected_mapping): + # This test is separate from the other request options because request headers must be strings + paginator = MagicMock() + paginator.get_request_headers.return_value = paginator_mapping + requester = MagicMock(use_cache=False) + + stream_slicer = MagicMock() + stream_slicer.get_request_headers.return_value = {"key_from_slicer": "value"} + + record_selector = MagicMock() + retriever = SimpleRetriever( + name="stream_name", + primary_key=primary_key, + requester=requester, + record_selector=record_selector, + stream_slicer=stream_slicer, + paginator=paginator, + ignore_stream_slicer_parameters_on_paginated_requests=ignore_stream_slicer_parameters_on_paginated_requests, + parameters={}, + config={}, + ) + + request_option_type_to_method = { + RequestOptionType.header: retriever._request_headers, + } + + for _, method in request_option_type_to_method.items(): + actual_mapping = method(None, None, next_page_token={"next_page_token": "1000"}) + assert expected_mapping == actual_mapping + + @pytest.mark.parametrize( "test_name, slicer_body_data, paginator_body_data, expected_body_data", [ From 9cb23714606b50da3b7955f9dd452f6a7389da6c Mon Sep 17 00:00:00 2001 From: girarda Date: Wed, 21 Feb 2024 22:20:18 +0000 Subject: [PATCH 09/74] =?UTF-8?q?=F0=9F=A4=96=20Bump=20minor=20version=20o?= =?UTF-8?q?f=20Python=20CDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airbyte-cdk/python/.bumpversion.cfg | 2 +- airbyte-cdk/python/CHANGELOG.md | 3 +++ airbyte-cdk/python/Dockerfile | 4 ++-- airbyte-cdk/python/setup.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/airbyte-cdk/python/.bumpversion.cfg b/airbyte-cdk/python/.bumpversion.cfg index 3998909aab1d..6389be4c7239 100644 --- a/airbyte-cdk/python/.bumpversion.cfg +++ b/airbyte-cdk/python/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.64.1 +current_version = 0.65.0 commit = False [bumpversion:file:setup.py] diff --git a/airbyte-cdk/python/CHANGELOG.md b/airbyte-cdk/python/CHANGELOG.md index d2c8909afc43..163c9bf4552b 100644 --- a/airbyte-cdk/python/CHANGELOG.md +++ b/airbyte-cdk/python/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.65.0 +low-code: Allow connectors to ignore stream slicer request options on paginated requests + ## 0.64.1 diff --git a/airbyte-cdk/python/Dockerfile b/airbyte-cdk/python/Dockerfile index 9fe635147342..b84acc6873b6 100644 --- a/airbyte-cdk/python/Dockerfile +++ b/airbyte-cdk/python/Dockerfile @@ -10,7 +10,7 @@ RUN apk --no-cache upgrade \ && apk --no-cache add tzdata build-base # install airbyte-cdk -RUN pip install --prefix=/install airbyte-cdk==0.64.1 +RUN pip install --prefix=/install airbyte-cdk==0.65.0 # build a clean environment FROM base @@ -32,5 +32,5 @@ ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] # needs to be the same as CDK -LABEL io.airbyte.version=0.64.1 +LABEL io.airbyte.version=0.65.0 LABEL io.airbyte.name=airbyte/source-declarative-manifest diff --git a/airbyte-cdk/python/setup.py b/airbyte-cdk/python/setup.py index 604e30a2bc0f..7c7b12e7dd89 100644 --- a/airbyte-cdk/python/setup.py +++ b/airbyte-cdk/python/setup.py @@ -36,7 +36,7 @@ name="airbyte-cdk", # The version of the airbyte-cdk package is used at runtime to validate manifests. That validation must be # updated if our semver format changes such as using release candidate versions. - version="0.64.1", + version="0.65.0", description="A framework for writing Airbyte Connectors.", long_description=README, long_description_content_type="text/markdown", From f106d11d1ca56450eab2d63c96d2a186ed86abfd Mon Sep 17 00:00:00 2001 From: Rodi Reich Zilberman <867491+rodireich@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:57:48 -0800 Subject: [PATCH 10/74] =?UTF-8?q?Mangle=20unhandled=20MongoCommandExceptio?= =?UTF-8?q?n=20to=20prevent=20creating=20grouping=20o=E2=80=A6=20(#35526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connectors/source-mongodb-v2/metadata.yaml | 2 +- .../io/airbyte/integrations/source/mongodb/MongoDbSource.java | 3 +++ docs/integrations/sources/mongodb-v2.md | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml b/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml index 6d9c000b4537..88bbd68ae98f 100644 --- a/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml +++ b/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: source definitionId: b2e713cd-cc36-4c0a-b5bd-b47cb8a0561e - dockerImageTag: 1.2.11 + dockerImageTag: 1.2.12 dockerRepository: airbyte/source-mongodb-v2 documentationUrl: https://docs.airbyte.com/integrations/sources/mongodb-v2 githubIssueLabel: source-mongodb-v2 diff --git a/airbyte-integrations/connectors/source-mongodb-v2/src/main/java/io/airbyte/integrations/source/mongodb/MongoDbSource.java b/airbyte-integrations/connectors/source-mongodb-v2/src/main/java/io/airbyte/integrations/source/mongodb/MongoDbSource.java index 2a6c15c28677..d7103f6fe854 100644 --- a/airbyte-integrations/connectors/source-mongodb-v2/src/main/java/io/airbyte/integrations/source/mongodb/MongoDbSource.java +++ b/airbyte-integrations/connectors/source-mongodb-v2/src/main/java/io/airbyte/integrations/source/mongodb/MongoDbSource.java @@ -6,10 +6,12 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.annotations.VisibleForTesting; +import com.mongodb.MongoCommandException; import com.mongodb.MongoSecurityException; import com.mongodb.client.MongoClient; import com.mongodb.connection.ClusterType; import io.airbyte.cdk.integrations.BaseConnector; +import io.airbyte.cdk.integrations.base.AirbyteExceptionHandler; import io.airbyte.cdk.integrations.base.AirbyteTraceMessageUtility; import io.airbyte.cdk.integrations.base.IntegrationRunner; import io.airbyte.cdk.integrations.base.Source; @@ -40,6 +42,7 @@ public MongoDbSource() { } public static void main(final String[] args) throws Exception { + AirbyteExceptionHandler.addThrowableForDeinterpolation(MongoCommandException.class); final Source source = new MongoDbSource(); LOGGER.info("starting source: {}", MongoDbSource.class); new IntegrationRunner(source).run(args); diff --git a/docs/integrations/sources/mongodb-v2.md b/docs/integrations/sources/mongodb-v2.md index 0df7d0f12a97..9894fd8d0568 100644 --- a/docs/integrations/sources/mongodb-v2.md +++ b/docs/integrations/sources/mongodb-v2.md @@ -214,6 +214,7 @@ For more information regarding configuration parameters, please see [MongoDb Doc | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:----------------------------------------------------------------------------------------------------------| +| 1.2.12 | 2024-02-21 | [35526](https://github.com/airbytehq/airbyte/pull/35526) | Improve error handling. | | 1.2.11 | 2024-02-20 | [35375](https://github.com/airbytehq/airbyte/pull/35375) | Add config to throw an error on invalid CDC position and enable it by default. | | 1.2.10 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | | 1.2.9 | 2024-02-13 | [35114](https://github.com/airbytehq/airbyte/pull/35114) | Extend subsequent cdc record wait time to the duration of initial. Bug Fixes | From d2b5ac692cdbd4eb35224e1229072f0fc4457118 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Wed, 21 Feb 2024 18:48:41 -0800 Subject: [PATCH 11/74] .github: fix java cdk publish workflow (#35533) --- .github/workflows/gradle.yml | 5 +- .../workflows/publish-java-cdk-command.yml | 141 +++++++----------- airbyte-cdk/java/airbyte-cdk/build.gradle | 30 ++-- 3 files changed, 77 insertions(+), 99 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c25e6d404b80..9f7837c6617b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -80,9 +80,12 @@ jobs: env: CI: true with: + job-id: gradle-check read-only: ${{ github.ref != 'refs/heads/master' }} + gradle-distribution-sha-256-sum-warning: false + concurrent: true # TODO: be able to remove the skipSlowTests property - arguments: --scan --no-daemon --no-watch-fs check -DskipSlowTests=true + arguments: --scan check -DskipSlowTests=true set-instatus-incident-on-failure: name: Create Instatus Incident on Failure diff --git a/.github/workflows/publish-java-cdk-command.yml b/.github/workflows/publish-java-cdk-command.yml index bce9961372bd..878f7273faf5 100644 --- a/.github/workflows/publish-java-cdk-command.yml +++ b/.github/workflows/publish-java-cdk-command.yml @@ -8,17 +8,10 @@ # /publish-java-cdk force=true # Force-publish if needing to replace an already published version name: Publish Java CDK on: - # Temporarily run on commits to the 'java-cdk/publish-workflow' branch. - # TODO: Remove this 'push' trigger before merging to master. - push: - branches: - - java-cdk/publish-workflow - workflow_dispatch: inputs: repo: description: "Repo to check out code from. Defaults to the main airbyte repo." - # TODO: If publishing from forks is needed, we'll need to revert type to `string` of `choice`. type: choice required: true default: airbytehq/airbyte @@ -30,7 +23,7 @@ on: type: boolean default: false force: - description: "Force release (ignore existing)" + description: "Force release (overwrite existing)" required: true type: boolean default: false @@ -40,9 +33,6 @@ on: comment-id: description: "Optional comment-id of the slash command. Ignore if not applicable." required: false - # uuid: - # description: "Custom UUID of workflow run. Used because GitHub dispatches endpoint does not return workflow run id." - # required: false concurrency: group: publish-airbyte-cdk @@ -50,59 +40,32 @@ concurrency: env: # Use the provided GITREF or default to the branch triggering the workflow. - REPO: ${{ github.event.inputs.repo }} GITREF: ${{ github.event.inputs.gitref || github.ref }} FORCE: "${{ github.event.inputs.force == null && 'false' || github.event.inputs.force }}" DRY_RUN: "${{ github.event.inputs.dry-run == null && 'true' || github.event.inputs.dry-run }}" CDK_VERSION_FILE_PATH: "./airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties" + S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} + S3_BUILD_CACHE_SECRET_KEY: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} jobs: - # We are using these runners because they are the same as the one for `publish-command.yml` - # One problem we had using `ubuntu-latest` for example is that the user is not root and some commands would fail in - # `manage.sh` (specifically `apt-get`) - start-publish-docker-image-runner-0: - name: Start Build EC2 Runner 0 - runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - repository: airbytehq/airbyte - ref: master - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Start AWS Runner - id: start-ec2-runner - uses: ./.github/actions/start-aws-runner - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - github-token: ${{ env.PAT }} - label: ${{ github.run_id }}-publisher - publish-cdk: name: Publish Java CDK - needs: start-publish-docker-image-runner-0 - runs-on: ubuntu-latest + runs-on: connector-test-large + timeout-minutes: 30 steps: - - name: Link comment to workflow run + - name: Link comment to Workflow Run if: github.event.inputs.comment-id uses: peter-evans/create-or-update-comment@v1 with: comment-id: ${{ github.event.inputs.comment-id }} body: | > :clock2: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} + - name: Checkout Airbyte uses: actions/checkout@v3 with: - repository: ${{ env.REPO }} ref: ${{ env.GITREF }} + - name: Read Target Java CDK version id: read-target-java-cdk-version run: | @@ -112,28 +75,57 @@ jobs: exit 1 fi echo "CDK_VERSION=${cdk_version}" >> $GITHUB_ENV + - name: Setup Java uses: actions/setup-java@v3 with: distribution: "zulu" java-version: "21" - - name: Check for already-published version (${{ env.CDK_VERSION }}, FORCE=${{ env.FORCE }}) - if: ${{ !(env.FORCE == 'true') }} - run: ./gradlew :airbyte-cdk:java:airbyte-cdk:assertCdkVersionNotPublished + + - name: Docker login + # Some tests use testcontainers which pull images from DockerHub. + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + - name: Build Java CDK - run: ./gradlew --no-daemon :airbyte-cdk:java:airbyte-cdk:build - - name: Upload jars as artifacts - if: ${{ !(env.DRY_RUN == 'false') }} - uses: actions/upload-artifact@v2 + uses: burrunan/gradle-cache-action@v1 + env: + CI: true with: - name: mavenlocal-jars - path: ~/.m2/repository/io/airbyte/ - - name: Publish Java Modules to CloudRepo + job-id: cdk-publish + read-only: ${{ !(env.DRY_RUN == 'false') }} + concurrent: true + gradle-distribution-sha-256-sum-warning: false + arguments: --scan :airbyte-cdk:java:airbyte-cdk:cdkBuild + + - name: Check for Existing Version + if: ${{ !(env.FORCE == 'true') }} + uses: burrunan/gradle-cache-action@v1 + env: + CI: true + with: + job-id: cdk-publish + read-only: true + concurrent: true + gradle-distribution-sha-256-sum-warning: false + arguments: --scan :airbyte-cdk:java:airbyte-cdk:assertCdkVersionNotPublished + + - name: Publish Poms and Jars to CloudRepo if: ${{ env.DRY_RUN == 'false' }} - run: ./gradlew --no-daemon :airbyte-cdk:java:airbyte-cdk:publish + uses: burrunan/gradle-cache-action@v1 env: + CI: true CLOUDREPO_USER: ${{ secrets.CLOUDREPO_USER }} CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_PASSWORD }} + with: + job-id: cdk-publish + read-only: true + concurrent: true + execution-only-caches: true + gradle-distribution-sha-256-sum-warning: false + arguments: --scan :airbyte-cdk:java:airbyte-cdk:cdkPublish - name: Add Success Comment if: github.event.inputs.comment-id && success() @@ -143,6 +135,7 @@ jobs: edit-mode: append body: | > :white_check_mark: Successfully published Java CDK ${{ env.CDK_VERSION }}! + - name: Add Failure Comment if: github.event.inputs.comment-id && failure() uses: peter-evans/create-or-update-comment@v1 @@ -151,7 +144,8 @@ jobs: edit-mode: append body: | > :x: Publish Java CDK ${{ env.CDK_VERSION }} failed! - - name: "Post failure to Slack channel `#dev-connectors-extensibility-releases`" + + - name: "Post failure to Slack channel" if: ${{ env.DRY_RUN == 'false' && failure() }} uses: slackapi/slack-github-action@v1.23.0 continue-on-error: true @@ -179,7 +173,8 @@ jobs: } env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_AIRBYTE_TEAM }} - - name: "Post success to Slack channel `#dev-connectors-extensibility-releases`" + + - name: "Post success to Slack channel" if: ${{ env.DRY_RUN == 'false' && !failure() }} uses: slackapi/slack-github-action@v1.23.0 continue-on-error: true @@ -207,33 +202,3 @@ jobs: } env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_AIRBYTE_TEAM }} - - # In case of self-hosted EC2 errors, remove this block. - stop-publish-docker-image-runner-0: - if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs - name: Stop Build EC2 Runner - needs: - - start-publish-docker-image-runner-0 # required to get output from the start-runner job - - publish-cdk # required to wait when the main job is done - runs-on: ubuntu-latest - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-2 - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Stop EC2 runner - uses: airbytehq/ec2-github-runner@base64v1.1.0 - with: - mode: stop - github-token: ${{ env.PAT }} - label: ${{ needs.start-publish-docker-image-runner-0.outputs.label }} - ec2-instance-id: ${{ needs.start-publish-docker-image-runner-0.outputs.ec2-instance-id }} diff --git a/airbyte-cdk/java/airbyte-cdk/build.gradle b/airbyte-cdk/java/airbyte-cdk/build.gradle index 18b8028bc095..f4abc2a918b9 100644 --- a/airbyte-cdk/java/airbyte-cdk/build.gradle +++ b/airbyte-cdk/java/airbyte-cdk/build.gradle @@ -1,3 +1,9 @@ +final var cdkVersion = { + var props = new Properties() + file("core/src/main/resources/version.properties").withInputStream(props::load) + return props.getProperty('version', 'undefined') +}() + allprojects { apply plugin: 'java-library' apply plugin: 'maven-publish' @@ -8,11 +14,14 @@ allprojects { def artifactBaseName = 'airbyte-cdk-' + project.name // E.g. airbyte-cdk-core, airbyte-cdk-db-sources, airbyte-cdk-db-destinations, etc. + project.version = cdkVersion + publishing { publications { main(MavenPublication) { groupId = 'io.airbyte.cdk' artifactId = artifactBaseName + version = project.version from components.java } testFixtures(MavenPublication) { @@ -46,17 +55,18 @@ allprojects { description = "Airbyte Connector Development Kit (CDK) for Java." +tasks.register('cdkBuild').configure { + dependsOn subprojects.collect { it.tasks.named('build') } +} +tasks.register('cdkPublish').configure { + dependsOn subprojects.collect { it.tasks.named('publish') } +} tasks.register('assertCdkVersionNotPublished') { doLast { - var props = new Properties() - file("core/src/main/resources/version.properties").withInputStream(props::load) - var checkGroupId = "io.airbyte.cdk" - var checkArtifactId = "airbyte-cdk-core" - var checkVersion = props.getProperty('version') ?: 'undefined' var repoUrl = "https://airbyte.mycloudrepo.io/public/repositories/airbyte-public-jars" - var groupIdUrl = "${repoUrl}/${checkGroupId.replace('.', '/')}" - var artifactUrl = "${groupIdUrl}/${checkArtifactId}/${checkVersion}/${checkArtifactId}-${checkVersion}.pom" + var groupIdUrl = "${repoUrl}/io/airbyte/cdk" + var artifactUrl = "${groupIdUrl}/airbyte-cdk-core/${project.version}/airbyte-cdk-core-${project.version}.pom" var connection = artifactUrl.toURL().openConnection() as HttpURLConnection connection.setRequestMethod("HEAD") @@ -65,11 +75,11 @@ tasks.register('assertCdkVersionNotPublished') { var responseCode = connection.getResponseCode() if (responseCode == 200) { - throw new GradleException("Java CDK '${checkVersion}' already published at ${groupIdUrl}") + throw new GradleException("Java CDK '${project.version}' already published at ${groupIdUrl}") } else if (responseCode == 404) { - logger.lifecycle("Java CDK '${checkVersion}' not yet published at ${groupIdUrl}.") + logger.lifecycle("Java CDK '${project.version}' not yet published at ${groupIdUrl}") } else { - throw new GradleException("Unexpected HTTP response code ${responseCode} from ${artifactUrl}, expected either 200 or 404.") + throw new GradleException("Unexpected HTTP response code ${responseCode} from ${artifactUrl} : expected either 200 or 404.") } } } From 1162302069f80c4c44bea7e3ec28d0454b67c98b Mon Sep 17 00:00:00 2001 From: Akash Kulkarni <113392464+akashkulk@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:24:56 -0800 Subject: [PATCH 12/74] [Source-mysql] : Adopt 0.21.4 and reduce cdc state compression threshold to 1MB (#35525) --- airbyte-cdk/java/airbyte-cdk/README.md | 190 +++++++++--------- .../connectors/source-mysql/build.gradle | 2 +- .../connectors/source-mysql/metadata.yaml | 2 +- docs/integrations/sources/mysql.md | 1 + 4 files changed, 98 insertions(+), 97 deletions(-) diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index 3fb31042d45d..879286dc0785 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -164,98 +164,98 @@ MavenLocal debugging steps: ### Java CDK -| Version | Date | Pull Request | Subject | -|:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Add Junit progress information to the test logs | -| 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | -| 0.21.2 | 2024-02-20 | [\#34978](https://github.com/airbytehq/airbyte/pull/34978) | Reduce log noise in NormalizationLogParser. | -| 0.21.1 | 2024-02-20 | [\#35199](https://github.com/airbytehq/airbyte/pull/35199) | Add thread names to the logs. | -| 0.21.0 | 2024-02-16 | [\#35314](https://github.com/airbytehq/airbyte/pull/35314) | Delete S3StreamCopier classes. These have been superseded by the async destinations framework. | -| 0.20.9 | 2024-02-15 | [\#35240](https://github.com/airbytehq/airbyte/pull/35240) | Make state emission to platform inside state manager itself. | -| 0.20.8 | 2024-02-15 | [\#35285](https://github.com/airbytehq/airbyte/pull/35285) | Improve blobstore module structure. | -| 0.20.7 | 2024-02-13 | [\#35236](https://github.com/airbytehq/airbyte/pull/35236) | output logs to files in addition to stdout when running tests | -| 0.20.6 | 2024-02-12 | [\#35036](https://github.com/airbytehq/airbyte/pull/35036) | Add trace utility to emit analytics messages. | -| 0.20.5 | 2024-02-13 | [\#34869](https://github.com/airbytehq/airbyte/pull/34869) | Don't emit final state in SourceStateIterator there is an underlying stream failure. | -| 0.20.4 | 2024-02-12 | [\#35042](https://github.com/airbytehq/airbyte/pull/35042) | Use delegate's isDestinationV2 invocation in SshWrappedDestination. | -| 0.20.3 | 2024-02-09 | [\#34580](https://github.com/airbytehq/airbyte/pull/34580) | Support special chars in mysql/mssql database name. | -| 0.20.2 | 2024-02-12 | [\#35111](https://github.com/airbytehq/airbyte/pull/35144) | Make state emission from async framework synchronized. | -| 0.20.1 | 2024-02-11 | [\#35111](https://github.com/airbytehq/airbyte/pull/35111) | Fix GlobalAsyncStateManager stats counting logic. | -| 0.20.0 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Add new test cases to BaseTypingDedupingTest to exercise special characters. | -| 0.19.0 | 2024-02-01 | [\#34745](https://github.com/airbytehq/airbyte/pull/34745) | Reorganize CDK module structure. | -| 0.18.0 | 2024-02-08 | [\#33606](https://github.com/airbytehq/airbyte/pull/33606) | Add updated Initial and Incremental Stream State definitions for DB Sources. | -| 0.17.1 | 2024-02-08 | [\#35027](https://github.com/airbytehq/airbyte/pull/35027) | Make state handling thread safe in async destination framework. | -| 0.17.0 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Enable configuring async destination batch size. | -| 0.16.6 | 2024-02-07 | [\#34892](https://github.com/airbytehq/airbyte/pull/34892) | Improved testcontainers logging and support for unshared containers. | -| 0.16.5 | 2024-02-07 | [\#34948](https://github.com/airbytehq/airbyte/pull/34948) | Fix source state stats counting logic | -| 0.16.4 | 2024-02-01 | [\#34727](https://github.com/airbytehq/airbyte/pull/34727) | Add future based stdout consumer in BaseTypingDedupingTest | -| 0.16.3 | 2024-01-30 | [\#34669](https://github.com/airbytehq/airbyte/pull/34669) | Fix org.apache.logging.log4j:log4j-slf4j-impl version conflicts. | -| 0.16.2 | 2024-01-29 | [\#34630](https://github.com/airbytehq/airbyte/pull/34630) | expose NamingTransformer to sub-classes in destinations JdbcSqlGenerator. | -| 0.16.1 | 2024-01-29 | [\#34533](https://github.com/airbytehq/airbyte/pull/34533) | Add a safe method to execute DatabaseMetadata's Resultset returning queries. | -| 0.16.0 | 2024-01-26 | [\#34573](https://github.com/airbytehq/airbyte/pull/34573) | Untangle Debezium harness dependencies. | -| 0.15.2 | 2024-01-25 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Improve airbyte-api build performance. | -| 0.15.1 | 2024-01-25 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Async destinations: Better logging when we fail to parse an AirbyteMessage | -| 0.15.0 | 2024-01-23 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Removed connector registry and micronaut dependencies. | -| 0.14.2 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Handle case-sensitivity in sentry error grouping | -| 0.14.1 | 2024-01-24 | [\#34468](https://github.com/airbytehq/airbyte/pull/34468) | Add wait for process to be done before ending sync in destination BaseTDTest | -| 0.14.0 | 2024-01-23 | [\#34461](https://github.com/airbytehq/airbyte/pull/34461) | Revert non backward compatible signature changes from 0.13.1 | -| 0.13.3 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Denote if destinations fully support Destinations V2 | -| 0.13.2 | 2024-01-18 | [\#34364](https://github.com/airbytehq/airbyte/pull/34364) | Better logging in mongo db source connector | -| 0.13.1 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Add postCreateTable hook in destination JdbcSqlGenerator | -| 0.13.0 | 2024-01-16 | [\#34177](https://github.com/airbytehq/airbyte/pull/34177) | Add `useExpensiveSafeCasting` param in JdbcSqlGenerator methods; add JdbcTypingDedupingTest fixture; other DV2-related changes | -| 0.12.1 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Add hook for additional destination specific checks to JDBC destination check method | -| 0.12.0 | 2024-01-10 | [\#33875](https://github.com/airbytehq/airbyte/pull/33875) | Upgrade sshd-mina to 2.11.1 | -| 0.11.5 | 2024-01-10 | [\#34119](https://github.com/airbytehq/airbyte/pull/34119) | Remove wal2json support for postgres+debezium. | -| 0.11.4 | 2024-01-09 | [\#33305](https://github.com/airbytehq/airbyte/pull/33305) | Source stats in incremental syncs | -| 0.11.3 | 2023-01-09 | [\#33658](https://github.com/airbytehq/airbyte/pull/33658) | Always fail when debezium fails, even if it happened during the setup phase. | -| 0.11.2 | 2024-01-09 | [\#33969](https://github.com/airbytehq/airbyte/pull/33969) | Destination state stats implementation | -| 0.11.1 | 2024-01-04 | [\#33727](https://github.com/airbytehq/airbyte/pull/33727) | SSH bastion heartbeats for Destinations | -| 0.11.0 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | DV2 T+D uses Sql struct to represent transactions; other T+D-related changes | -| 0.10.4 | 2023-12-20 | [\#33071](https://github.com/airbytehq/airbyte/pull/33071) | Add the ability to parse JDBC parameters with another delimiter than '&' | -| 0.10.3 | 2024-01-03 | [\#33312](https://github.com/airbytehq/airbyte/pull/33312) | Send out count in AirbyteStateMessage | -| 0.10.1 | 2023-12-21 | [\#33723](https://github.com/airbytehq/airbyte/pull/33723) | Make memory-manager log message less scary | -| 0.10.0 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | JdbcDestinationHandler now properly implements `getInitialRawTableState`; reenable SqlGenerator test | -| 0.9.0 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation, exclude the T&D module from the CDK | -| 0.8.0 | 2023-12-18 | [\#33506](https://github.com/airbytehq/airbyte/pull/33506) | Improve async destination shutdown logic; more JDBC async migration work; improve DAT test schema handling | -| 0.7.9 | 2023-12-18 | [\#33549](https://github.com/airbytehq/airbyte/pull/33549) | Improve MongoDB logging. | -| 0.7.8 | 2023-12-18 | [\#33365](https://github.com/airbytehq/airbyte/pull/33365) | Emit stream statuses more consistently | -| 0.7.7 | 2023-12-18 | [\#33434](https://github.com/airbytehq/airbyte/pull/33307) | Remove LEGACY state | -| 0.7.6 | 2023-12-14 | [\#32328](https://github.com/airbytehq/airbyte/pull/33307) | Add schema less mode for mongodb CDC. Fixes for non standard mongodb id type. | -| 0.7.4 | 2023-12-13 | [\#33232](https://github.com/airbytehq/airbyte/pull/33232) | Track stream record count during sync; only run T+D if a stream had nonzero records or the previous sync left unprocessed records. | -| 0.7.3 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Extract shared JDBC T+D code. | -| 0.7.2 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | Fix DV2 JDBC type mappings (code changes in [\#33307](https://github.com/airbytehq/airbyte/pull/33307)). | -| 0.7.1 | 2023-12-01 | [\#33027](https://github.com/airbytehq/airbyte/pull/33027) | Add the abstract DB source debugger. | -| 0.7.0 | 2023-12-07 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Destinations V2 changes for JDBC destinations | -| 0.6.4 | 2023-12-06 | [\#33082](https://github.com/airbytehq/airbyte/pull/33082) | Improvements to schema snapshot error handling + schema snapshot history scope (scoped to configured DB). | -| 0.6.2 | 2023-11-30 | [\#32573](https://github.com/airbytehq/airbyte/pull/32573) | Update MSSQLConverter to enforce 6-digit microsecond precision for timestamp fields | -| 0.6.1 | 2023-11-30 | [\#32610](https://github.com/airbytehq/airbyte/pull/32610) | Support DB initial sync using binary as primary key. | -| 0.6.0 | 2023-11-30 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | JDBC destinations now use the async framework | -| 0.5.3 | 2023-11-28 | [\#32686](https://github.com/airbytehq/airbyte/pull/32686) | Better attribution of debezium engine shutdown due to heartbeat. | -| 0.5.1 | 2023-11-27 | [\#32662](https://github.com/airbytehq/airbyte/pull/32662) | Debezium initialization wait time will now read from initial setup time. | -| 0.5.0 | 2023-11-22 | [\#32656](https://github.com/airbytehq/airbyte/pull/32656) | Introduce TestDatabase test fixture, refactor database source test base classes. | -| 0.4.11 | 2023-11-14 | [\#32526](https://github.com/airbytehq/airbyte/pull/32526) | Clean up memory manager logs. | -| 0.4.10 | 2023-11-13 | [\#32285](https://github.com/airbytehq/airbyte/pull/32285) | Fix UUID codec ordering for MongoDB connector | -| 0.4.9 | 2023-11-13 | [\#32468](https://github.com/airbytehq/airbyte/pull/32468) | Further error grouping improvements for DV2 connectors | -| 0.4.8 | 2023-11-09 | [\#32377](https://github.com/airbytehq/airbyte/pull/32377) | source-postgres tests: skip dropping database | -| 0.4.7 | 2023-11-08 | [\#31856](https://github.com/airbytehq/airbyte/pull/31856) | source-postgres: support for infinity date and timestamps | -| 0.4.5 | 2023-11-07 | [\#32112](https://github.com/airbytehq/airbyte/pull/32112) | Async destinations framework: Allow configuring the queue flush threshold | -| 0.4.4 | 2023-11-06 | [\#32119](https://github.com/airbytehq/airbyte/pull/32119) | Add STANDARD UUID codec to MongoDB debezium handler | -| 0.4.2 | 2023-11-06 | [\#32190](https://github.com/airbytehq/airbyte/pull/32190) | Improve error deinterpolation | -| 0.4.1 | 2023-11-02 | [\#32192](https://github.com/airbytehq/airbyte/pull/32192) | Add 's3-destinations' CDK module. | -| 0.4.0 | 2023-11-02 | [\#32050](https://github.com/airbytehq/airbyte/pull/32050) | Fix compiler warnings. | -| 0.3.0 | 2023-11-02 | [\#31983](https://github.com/airbytehq/airbyte/pull/31983) | Add deinterpolation feature to AirbyteExceptionHandler. | -| 0.2.4 | 2023-10-31 | [\#31807](https://github.com/airbytehq/airbyte/pull/31807) | Handle case of debezium update and delete of records in mongodb. | -| 0.2.3 | 2023-10-31 | [\#32022](https://github.com/airbytehq/airbyte/pull/32022) | Update Debezium version from 2.20 -> 2.4.0. | -| 0.2.2 | 2023-10-31 | [\#31976](https://github.com/airbytehq/airbyte/pull/31976) | Debezium tweaks to make tests run faster. | -| 0.2.0 | 2023-10-30 | [\#31960](https://github.com/airbytehq/airbyte/pull/31960) | Hoist top-level gradle subprojects into CDK. | -| 0.1.12 | 2023-10-24 | [\#31674](https://github.com/airbytehq/airbyte/pull/31674) | Fail sync when Debezium does not shut down properly. | -| 0.1.11 | 2023-10-18 | [\#31486](https://github.com/airbytehq/airbyte/pull/31486) | Update constants in AdaptiveSourceRunner. | -| 0.1.9 | 2023-10-12 | [\#31309](https://github.com/airbytehq/airbyte/pull/31309) | Use toPlainString() when handling BigDecimals in PostgresConverter | -| 0.1.8 | 2023-10-11 | [\#31322](https://github.com/airbytehq/airbyte/pull/31322) | Cap log line length to 32KB to prevent loss of records | -| 0.1.7 | 2023-10-10 | [\#31194](https://github.com/airbytehq/airbyte/pull/31194) | Deallocate unused per stream buffer memory when empty | -| 0.1.6 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | -| 0.1.5 | 2023-10-09 | [\#31196](https://github.com/airbytehq/airbyte/pull/31196) | Update typo in CDK (CDN_LSN -> CDC_LSN) | -| 0.1.4 | 2023-10-06 | [\#31139](https://github.com/airbytehq/airbyte/pull/31139) | Reduce async buffer | -| 0.1.1 | 2023-09-28 | [\#30835](https://github.com/airbytehq/airbyte/pull/30835) | JDBC destinations now avoid staging area name collisions by using the raw table name as the stage name. (previously we used the stream name as the stage name) | -| 0.1.0 | 2023-09-27 | [\#30445](https://github.com/airbytehq/airbyte/pull/30445) | First launch, including shared classes for all connectors. | -| 0.0.2 | 2023-08-21 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Version bump only (no other changes). | -| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | +| Version | Date | Pull Request | Subject | +|:--------|:-----------|:-----------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Reduce CDC state compression limit to 1MB | +| 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | +| 0.21.2 | 2024-02-20 | [\#34978](https://github.com/airbytehq/airbyte/pull/34978) | Reduce log noise in NormalizationLogParser. | +| 0.21.1 | 2024-02-20 | [\#35199](https://github.com/airbytehq/airbyte/pull/35199) | Add thread names to the logs. | +| 0.21.0 | 2024-02-16 | [\#35314](https://github.com/airbytehq/airbyte/pull/35314) | Delete S3StreamCopier classes. These have been superseded by the async destinations framework. | +| 0.20.9 | 2024-02-15 | [\#35240](https://github.com/airbytehq/airbyte/pull/35240) | Make state emission to platform inside state manager itself. | +| 0.20.8 | 2024-02-15 | [\#35285](https://github.com/airbytehq/airbyte/pull/35285) | Improve blobstore module structure. | +| 0.20.7 | 2024-02-13 | [\#35236](https://github.com/airbytehq/airbyte/pull/35236) | output logs to files in addition to stdout when running tests | +| 0.20.6 | 2024-02-12 | [\#35036](https://github.com/airbytehq/airbyte/pull/35036) | Add trace utility to emit analytics messages. | +| 0.20.5 | 2024-02-13 | [\#34869](https://github.com/airbytehq/airbyte/pull/34869) | Don't emit final state in SourceStateIterator there is an underlying stream failure. | +| 0.20.4 | 2024-02-12 | [\#35042](https://github.com/airbytehq/airbyte/pull/35042) | Use delegate's isDestinationV2 invocation in SshWrappedDestination. | +| 0.20.3 | 2024-02-09 | [\#34580](https://github.com/airbytehq/airbyte/pull/34580) | Support special chars in mysql/mssql database name. | +| 0.20.2 | 2024-02-12 | [\#35111](https://github.com/airbytehq/airbyte/pull/35144) | Make state emission from async framework synchronized. | +| 0.20.1 | 2024-02-11 | [\#35111](https://github.com/airbytehq/airbyte/pull/35111) | Fix GlobalAsyncStateManager stats counting logic. | +| 0.20.0 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Add new test cases to BaseTypingDedupingTest to exercise special characters. | +| 0.19.0 | 2024-02-01 | [\#34745](https://github.com/airbytehq/airbyte/pull/34745) | Reorganize CDK module structure. | +| 0.18.0 | 2024-02-08 | [\#33606](https://github.com/airbytehq/airbyte/pull/33606) | Add updated Initial and Incremental Stream State definitions for DB Sources. | +| 0.17.1 | 2024-02-08 | [\#35027](https://github.com/airbytehq/airbyte/pull/35027) | Make state handling thread safe in async destination framework. | +| 0.17.0 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Enable configuring async destination batch size. | +| 0.16.6 | 2024-02-07 | [\#34892](https://github.com/airbytehq/airbyte/pull/34892) | Improved testcontainers logging and support for unshared containers. | +| 0.16.5 | 2024-02-07 | [\#34948](https://github.com/airbytehq/airbyte/pull/34948) | Fix source state stats counting logic | +| 0.16.4 | 2024-02-01 | [\#34727](https://github.com/airbytehq/airbyte/pull/34727) | Add future based stdout consumer in BaseTypingDedupingTest | +| 0.16.3 | 2024-01-30 | [\#34669](https://github.com/airbytehq/airbyte/pull/34669) | Fix org.apache.logging.log4j:log4j-slf4j-impl version conflicts. | +| 0.16.2 | 2024-01-29 | [\#34630](https://github.com/airbytehq/airbyte/pull/34630) | expose NamingTransformer to sub-classes in destinations JdbcSqlGenerator. | +| 0.16.1 | 2024-01-29 | [\#34533](https://github.com/airbytehq/airbyte/pull/34533) | Add a safe method to execute DatabaseMetadata's Resultset returning queries. | +| 0.16.0 | 2024-01-26 | [\#34573](https://github.com/airbytehq/airbyte/pull/34573) | Untangle Debezium harness dependencies. | +| 0.15.2 | 2024-01-25 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Improve airbyte-api build performance. | +| 0.15.1 | 2024-01-25 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Async destinations: Better logging when we fail to parse an AirbyteMessage | +| 0.15.0 | 2024-01-23 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Removed connector registry and micronaut dependencies. | +| 0.14.2 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Handle case-sensitivity in sentry error grouping | +| 0.14.1 | 2024-01-24 | [\#34468](https://github.com/airbytehq/airbyte/pull/34468) | Add wait for process to be done before ending sync in destination BaseTDTest | +| 0.14.0 | 2024-01-23 | [\#34461](https://github.com/airbytehq/airbyte/pull/34461) | Revert non backward compatible signature changes from 0.13.1 | +| 0.13.3 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Denote if destinations fully support Destinations V2 | +| 0.13.2 | 2024-01-18 | [\#34364](https://github.com/airbytehq/airbyte/pull/34364) | Better logging in mongo db source connector | +| 0.13.1 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Add postCreateTable hook in destination JdbcSqlGenerator | +| 0.13.0 | 2024-01-16 | [\#34177](https://github.com/airbytehq/airbyte/pull/34177) | Add `useExpensiveSafeCasting` param in JdbcSqlGenerator methods; add JdbcTypingDedupingTest fixture; other DV2-related changes | +| 0.12.1 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Add hook for additional destination specific checks to JDBC destination check method | +| 0.12.0 | 2024-01-10 | [\#33875](https://github.com/airbytehq/airbyte/pull/33875) | Upgrade sshd-mina to 2.11.1 | +| 0.11.5 | 2024-01-10 | [\#34119](https://github.com/airbytehq/airbyte/pull/34119) | Remove wal2json support for postgres+debezium. | +| 0.11.4 | 2024-01-09 | [\#33305](https://github.com/airbytehq/airbyte/pull/33305) | Source stats in incremental syncs | +| 0.11.3 | 2023-01-09 | [\#33658](https://github.com/airbytehq/airbyte/pull/33658) | Always fail when debezium fails, even if it happened during the setup phase. | +| 0.11.2 | 2024-01-09 | [\#33969](https://github.com/airbytehq/airbyte/pull/33969) | Destination state stats implementation | +| 0.11.1 | 2024-01-04 | [\#33727](https://github.com/airbytehq/airbyte/pull/33727) | SSH bastion heartbeats for Destinations | +| 0.11.0 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | DV2 T+D uses Sql struct to represent transactions; other T+D-related changes | +| 0.10.4 | 2023-12-20 | [\#33071](https://github.com/airbytehq/airbyte/pull/33071) | Add the ability to parse JDBC parameters with another delimiter than '&' | +| 0.10.3 | 2024-01-03 | [\#33312](https://github.com/airbytehq/airbyte/pull/33312) | Send out count in AirbyteStateMessage | +| 0.10.1 | 2023-12-21 | [\#33723](https://github.com/airbytehq/airbyte/pull/33723) | Make memory-manager log message less scary | +| 0.10.0 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | JdbcDestinationHandler now properly implements `getInitialRawTableState`; reenable SqlGenerator test | +| 0.9.0 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation, exclude the T&D module from the CDK | +| 0.8.0 | 2023-12-18 | [\#33506](https://github.com/airbytehq/airbyte/pull/33506) | Improve async destination shutdown logic; more JDBC async migration work; improve DAT test schema handling | +| 0.7.9 | 2023-12-18 | [\#33549](https://github.com/airbytehq/airbyte/pull/33549) | Improve MongoDB logging. | +| 0.7.8 | 2023-12-18 | [\#33365](https://github.com/airbytehq/airbyte/pull/33365) | Emit stream statuses more consistently | +| 0.7.7 | 2023-12-18 | [\#33434](https://github.com/airbytehq/airbyte/pull/33307) | Remove LEGACY state | +| 0.7.6 | 2023-12-14 | [\#32328](https://github.com/airbytehq/airbyte/pull/33307) | Add schema less mode for mongodb CDC. Fixes for non standard mongodb id type. | +| 0.7.4 | 2023-12-13 | [\#33232](https://github.com/airbytehq/airbyte/pull/33232) | Track stream record count during sync; only run T+D if a stream had nonzero records or the previous sync left unprocessed records. | +| 0.7.3 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Extract shared JDBC T+D code. | +| 0.7.2 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | Fix DV2 JDBC type mappings (code changes in [\#33307](https://github.com/airbytehq/airbyte/pull/33307)). | +| 0.7.1 | 2023-12-01 | [\#33027](https://github.com/airbytehq/airbyte/pull/33027) | Add the abstract DB source debugger. | +| 0.7.0 | 2023-12-07 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Destinations V2 changes for JDBC destinations | +| 0.6.4 | 2023-12-06 | [\#33082](https://github.com/airbytehq/airbyte/pull/33082) | Improvements to schema snapshot error handling + schema snapshot history scope (scoped to configured DB). | +| 0.6.2 | 2023-11-30 | [\#32573](https://github.com/airbytehq/airbyte/pull/32573) | Update MSSQLConverter to enforce 6-digit microsecond precision for timestamp fields | +| 0.6.1 | 2023-11-30 | [\#32610](https://github.com/airbytehq/airbyte/pull/32610) | Support DB initial sync using binary as primary key. | +| 0.6.0 | 2023-11-30 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | JDBC destinations now use the async framework | +| 0.5.3 | 2023-11-28 | [\#32686](https://github.com/airbytehq/airbyte/pull/32686) | Better attribution of debezium engine shutdown due to heartbeat. | +| 0.5.1 | 2023-11-27 | [\#32662](https://github.com/airbytehq/airbyte/pull/32662) | Debezium initialization wait time will now read from initial setup time. | +| 0.5.0 | 2023-11-22 | [\#32656](https://github.com/airbytehq/airbyte/pull/32656) | Introduce TestDatabase test fixture, refactor database source test base classes. | +| 0.4.11 | 2023-11-14 | [\#32526](https://github.com/airbytehq/airbyte/pull/32526) | Clean up memory manager logs. | +| 0.4.10 | 2023-11-13 | [\#32285](https://github.com/airbytehq/airbyte/pull/32285) | Fix UUID codec ordering for MongoDB connector | +| 0.4.9 | 2023-11-13 | [\#32468](https://github.com/airbytehq/airbyte/pull/32468) | Further error grouping improvements for DV2 connectors | +| 0.4.8 | 2023-11-09 | [\#32377](https://github.com/airbytehq/airbyte/pull/32377) | source-postgres tests: skip dropping database | +| 0.4.7 | 2023-11-08 | [\#31856](https://github.com/airbytehq/airbyte/pull/31856) | source-postgres: support for infinity date and timestamps | +| 0.4.5 | 2023-11-07 | [\#32112](https://github.com/airbytehq/airbyte/pull/32112) | Async destinations framework: Allow configuring the queue flush threshold | +| 0.4.4 | 2023-11-06 | [\#32119](https://github.com/airbytehq/airbyte/pull/32119) | Add STANDARD UUID codec to MongoDB debezium handler | +| 0.4.2 | 2023-11-06 | [\#32190](https://github.com/airbytehq/airbyte/pull/32190) | Improve error deinterpolation | +| 0.4.1 | 2023-11-02 | [\#32192](https://github.com/airbytehq/airbyte/pull/32192) | Add 's3-destinations' CDK module. | +| 0.4.0 | 2023-11-02 | [\#32050](https://github.com/airbytehq/airbyte/pull/32050) | Fix compiler warnings. | +| 0.3.0 | 2023-11-02 | [\#31983](https://github.com/airbytehq/airbyte/pull/31983) | Add deinterpolation feature to AirbyteExceptionHandler. | +| 0.2.4 | 2023-10-31 | [\#31807](https://github.com/airbytehq/airbyte/pull/31807) | Handle case of debezium update and delete of records in mongodb. | +| 0.2.3 | 2023-10-31 | [\#32022](https://github.com/airbytehq/airbyte/pull/32022) | Update Debezium version from 2.20 -> 2.4.0. | +| 0.2.2 | 2023-10-31 | [\#31976](https://github.com/airbytehq/airbyte/pull/31976) | Debezium tweaks to make tests run faster. | +| 0.2.0 | 2023-10-30 | [\#31960](https://github.com/airbytehq/airbyte/pull/31960) | Hoist top-level gradle subprojects into CDK. | +| 0.1.12 | 2023-10-24 | [\#31674](https://github.com/airbytehq/airbyte/pull/31674) | Fail sync when Debezium does not shut down properly. | +| 0.1.11 | 2023-10-18 | [\#31486](https://github.com/airbytehq/airbyte/pull/31486) | Update constants in AdaptiveSourceRunner. | +| 0.1.9 | 2023-10-12 | [\#31309](https://github.com/airbytehq/airbyte/pull/31309) | Use toPlainString() when handling BigDecimals in PostgresConverter | +| 0.1.8 | 2023-10-11 | [\#31322](https://github.com/airbytehq/airbyte/pull/31322) | Cap log line length to 32KB to prevent loss of records | +| 0.1.7 | 2023-10-10 | [\#31194](https://github.com/airbytehq/airbyte/pull/31194) | Deallocate unused per stream buffer memory when empty | +| 0.1.6 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | +| 0.1.5 | 2023-10-09 | [\#31196](https://github.com/airbytehq/airbyte/pull/31196) | Update typo in CDK (CDN_LSN -> CDC_LSN) | +| 0.1.4 | 2023-10-06 | [\#31139](https://github.com/airbytehq/airbyte/pull/31139) | Reduce async buffer | +| 0.1.1 | 2023-09-28 | [\#30835](https://github.com/airbytehq/airbyte/pull/30835) | JDBC destinations now avoid staging area name collisions by using the raw table name as the stage name. (previously we used the stream name as the stage name) | +| 0.1.0 | 2023-09-27 | [\#30445](https://github.com/airbytehq/airbyte/pull/30445) | First launch, including shared classes for all connectors. | +| 0.0.2 | 2023-08-21 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Version bump only (no other changes). | +| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-mysql/build.gradle b/airbyte-integrations/connectors/source-mysql/build.gradle index a4dd5c22b0b5..daeccabc9ec1 100644 --- a/airbyte-integrations/connectors/source-mysql/build.gradle +++ b/airbyte-integrations/connectors/source-mysql/build.gradle @@ -6,7 +6,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.20.6' + cdkVersionRequired = '0.21.4' features = ['db-sources'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/source-mysql/metadata.yaml b/airbyte-integrations/connectors/source-mysql/metadata.yaml index f63c1375e894..f336314ed65b 100644 --- a/airbyte-integrations/connectors/source-mysql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mysql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: 435bb9a5-7887-4809-aa58-28c27df0d7ad - dockerImageTag: 3.3.8 + dockerImageTag: 3.3.9 dockerRepository: airbyte/source-mysql documentationUrl: https://docs.airbyte.com/integrations/sources/mysql githubIssueLabel: source-mysql diff --git a/docs/integrations/sources/mysql.md b/docs/integrations/sources/mysql.md index 18e59658342d..d6d50b1ab4be 100644 --- a/docs/integrations/sources/mysql.md +++ b/docs/integrations/sources/mysql.md @@ -223,6 +223,7 @@ Any database or table encoding combination of charset and collation is supported | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.3.9 | 2024-02-21 | [35525](https://github.com/airbytehq/airbyte/pull/35338) | Adopt 0.21.4 and reduce cdc state compression threshold to 1MB. | | 3.3.8 | 2024-02-20 | [35338](https://github.com/airbytehq/airbyte/pull/35338) | Add config to throw an error on invalid CDC position. | | 3.3.7 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | | 3.3.6 | 2024-02-13 | [34869](https://github.com/airbytehq/airbyte/pull/34573) | Don't emit state in SourceStateIterator when there is an underlying stream failure. | From 833f3368a7fa9ea19648bf84bdc69dbb4de8ebda Mon Sep 17 00:00:00 2001 From: Daryna Ishchenko <80129833+darynaishchenko@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:14:54 +0200 Subject: [PATCH 13/74] :hospital: Source Notion: update stream schema (#35409) --- .../integration_tests/expected_records.jsonl | 6 +- .../connectors/source-notion/metadata.yaml | 2 +- .../connectors/source-notion/pyproject.toml | 2 +- .../schemas/shared/rich_text.json | 11 +++ .../source_notion/schemas/shared/user.json | 28 +++++++ .../source-notion/source_notion/streams.py | 32 +++++++- .../source-notion/unit_tests/test_streams.py | 38 +++++++++ docs/integrations/sources/notion.md | 81 ++++++++++--------- 8 files changed, 154 insertions(+), 46 deletions(-) diff --git a/airbyte-integrations/connectors/source-notion/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-notion/integration_tests/expected_records.jsonl index 27bf2dc60ca8..9989f84792de 100644 --- a/airbyte-integrations/connectors/source-notion/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-notion/integration_tests/expected_records.jsonl @@ -1,9 +1,9 @@ {"stream": "users", "data": {"object": "user", "id": "5612c094-99ec-4ba3-ac7f-df8d84c8d6be", "name": "Sherif Nada", "avatar_url": "https://s3-us-west-2.amazonaws.com/public.notion-static.com/305f7efc-2862-4342-ba99-5023f3e34717/6246757.png", "type": "person", "person": {"email": "sherif@airbyte.io"}}, "emitted_at": 1697023279924} {"stream": "users", "data": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a", "name": "Airyte", "avatar_url": null, "type": "person", "person": {"email": "integration-test@airbyte.io"}}, "emitted_at": 1697023279925} {"stream": "users", "data": {"object": "user", "id": "c1ff0160-b2af-497a-aab7-8b61e625e4e3", "name": "Gil Cho", "avatar_url": "https://lh3.googleusercontent.com/a/ALm5wu0ElXfvy3YfVUyRn-aB9EZy5AZ1ougHuNyCGmO2=s100", "type": "person", "person": {"email": "gil@airbyte.io"}}, "emitted_at": 1697023279925} -{"stream": "databases", "data": {"object": "database", "id": "b75d2e55-cc80-4afa-a273-c78178ac6b3f", "cover": null, "icon": {"type": "emoji", "emoji": "\ud83d\ude4b"}, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_time": "2021-10-19T13:33:00.000Z", "title": [{"type": "text", "text": {"content": "Engineering Directory ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Engineering Directory ", "href": null}], "description": [{"type": "text", "text": {"content": "Have a question about part of our codebase?\nFind the most knowledgeable person in this directory.\nLearn more about ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Have a question about part of our codebase?\nFind the most knowledgeable person in this directory.\nLearn more about ", "href": null}, {"type": "text", "text": {"content": "Notion databases", "link": {"url": "https://www.notion.so/notion/Database-101-build-and-view-fd8cd2d212f74c50954c11086d85997e"}}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Notion databases", "href": "https://www.notion.so/notion/Database-101-build-and-view-fd8cd2d212f74c50954c11086d85997e"}, {"type": "text", "text": {"content": ".", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": ".", "href": null}], "is_inline": false, "properties": [{"name": "Date Added", "value": {"id": "%2Fkv%22", "name": "Date Added", "type": "created_time", "created_time": {}}}, {"name": "Notes", "value": {"id": "mq%22D", "name": "Notes", "type": "rich_text", "rich_text": {}}}, {"name": "Person", "value": {"id": "uiZ%26", "name": "Person", "type": "people", "people": {}}}, {"name": "Name", "value": {"id": "title", "name": "Name", "type": "title", "title": {}}}], "parent": {"type": "block_id", "block_id": "b81f8caf-3ec4-4455-9a0b-25c2bd3b60cb"}, "url": "https://www.notion.so/b75d2e55cc804afaa273c78178ac6b3f", "public_url": null, "archived": false}, "emitted_at": 1697023281967} -{"stream": "databases", "data": {"object": "database", "id": "fbff7d4e-eca4-4432-91e6-ec64ba4b5a98", "cover": null, "icon": null, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_time": "2021-10-19T13:33:00.000Z", "title": [{"type": "text", "text": {"content": "Questions", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Questions", "href": null}], "description": [], "is_inline": true, "properties": [{"name": "Difficulty", "value": {"id": "'i6%2F", "name": "Difficulty", "type": "select", "select": {"options": [{"id": "f00068b9-7612-45da-91ad-1a7b1d259375", "name": "Easy", "color": "green"}, {"id": "8e244bfe-d4c7-48c5-9088-ffd6926b4ba0", "name": "Medium", "color": "yellow"}, {"id": "9ab57ef4-eab1-4b20-a502-047610b5c97d", "name": "Hard", "color": "red"}]}}}, {"name": "Skills", "value": {"id": "K%3AtR", "name": "Skills", "type": "multi_select", "multi_select": {"options": [{"id": "72f4d134-a773-48c1-ba3d-b529f55c6818", "name": "Front end", "color": "default"}, {"id": "c20f5d57-3e35-4b39-b556-05071203cc1a", "name": "Backend", "color": "default"}, {"id": "31d5735c-d6ba-4bd7-940f-bdcb36091c02", "name": "Architecture", "color": "default"}, {"id": "0398de54-af68-4c3a-9953-3788e8eaadbf", "name": "Algorithms", "color": "default"}, {"id": "df9dff09-7dea-4409-a10f-b5e2b546ad94", "name": "Data Structures", "color": "default"}]}}}, {"name": "Question Name", "value": {"id": "title", "name": "Question Name", "type": "title", "title": {}}}], "parent": {"type": "page_id", "page_id": "4999109d-1b7b-41a2-abb4-84f6b961ee74"}, "url": "https://www.notion.so/fbff7d4eeca4443291e6ec64ba4b5a98", "public_url": null, "archived": false}, "emitted_at": 1697023281968} -{"stream": "databases", "data": {"object": "database", "id": "9b1ce91e-a93a-437c-8c92-81083cd98540", "cover": null, "icon": {"type": "emoji", "emoji": "\u270f\ufe0f"}, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "ec324c09-af75-40f0-b91a-49ded74fdaf5"}, "last_edited_time": "2023-09-13T00:06:00.000Z", "title": [{"type": "text", "text": {"content": "Meeting Notes", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Meeting Notes", "href": null}], "description": [{"type": "text", "text": {"content": "Use this template to capture notes from all meetings in one accessible spot.\nNotes can be tagged by meeting type to make them easy to find. \nSee when each meeting took place and who was there.\n\n", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Use this template to capture notes from all meetings in one accessible spot.\nNotes can be tagged by meeting type to make them easy to find. \nSee when each meeting took place and who was there.\n\n", "href": null}, {"type": "text", "text": {"content": "\u2193", "link": null}, "annotations": {"bold": true, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "\u2193", "href": null}, {"type": "text", "text": {"content": " Click ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": " Click ", "href": null}, {"type": "text", "text": {"content": "List View", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": true, "color": "default"}, "plain_text": "List View", "href": null}, {"type": "text", "text": {"content": " to create and see other views, including a board organized by meeting type.", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": " to create and see other views, including a board organized by meeting type.", "href": null}], "is_inline": false, "properties": [{"name": "Last Edited Time", "value": {"id": "0AiB", "name": "Last Edited Time", "type": "last_edited_time", "last_edited_time": {}}}, {"name": "Created By", "value": {"id": "F%5D)%3F", "name": "Created By", "type": "created_by", "created_by": {}}}, {"name": "Created", "value": {"id": "Ird4", "name": "Created", "type": "created_time", "created_time": {}}}, {"name": "Type", "value": {"id": "_%7B%5C7", "name": "Type", "type": "select", "select": {"options": [{"id": "3a8fd64c-899d-4c39-ba97-ac4f565d6e94", "name": "Post-mortem", "color": "red"}, {"id": "28b68013-20d5-4824-b810-45cde8784581", "name": "Standup", "color": "green"}, {"id": "8ee247a9-cb60-430a-9ea6-d5c053253334", "name": "Weekly Sync", "color": "blue"}, {"id": "5fb57c36-999f-49e2-b153-96531d086862", "name": "Sprint Planning", "color": "yellow"}, {"id": "1747fcca-8207-42c8-802f-fd43965c016a", "name": "Ad Hoc", "color": "orange"}]}}}, {"name": "Participants", "value": {"id": "b%3AeA", "name": "Participants", "type": "people", "people": {}}}, {"name": "Name", "value": {"id": "title", "name": "Name", "type": "title", "title": {}}}], "parent": {"type": "workspace", "workspace": true}, "url": "https://www.notion.so/9b1ce91ea93a437c8c9281083cd98540", "public_url": null, "archived": false}, "emitted_at": 1697023281968} +{"stream": "databases", "data": {"object": "database", "id": "b75d2e55-cc80-4afa-a273-c78178ac6b3f", "cover": null, "icon": {"type": "emoji", "emoji": "\ud83d\ude4b"}, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_time": "2021-10-19T13:33:00.000Z", "title": [{"type": "text", "text": {"content": "Engineering Directory ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Engineering Directory ", "href": null}], "description": [{"type": "text", "text": {"content": "Have a question about part of our codebase?\nFind the most knowledgeable person in this directory.\nLearn more about ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Have a question about part of our codebase?\nFind the most knowledgeable person in this directory.\nLearn more about ", "href": null}, {"type": "text", "text": {"content": "Notion databases", "link": {"url": "https://www.notion.so/notion/Database-101-build-and-view-fd8cd2d212f74c50954c11086d85997e"}}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Notion databases", "href": "https://www.notion.so/notion/Database-101-build-and-view-fd8cd2d212f74c50954c11086d85997e"}, {"type": "text", "text": {"content": ".", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": ".", "href": null}], "is_inline": false, "properties": [{"name": "Date Added", "value": {"id": "%2Fkv%22", "name": "Date Added", "type": "created_time", "created_time": {}}}, {"name": "Notes", "value": {"id": "mq%22D", "name": "Notes", "type": "rich_text", "rich_text": {}}}, {"name": "Person", "value": {"id": "uiZ%26", "name": "Person", "type": "people", "people": {}}}, {"name": "Name", "value": {"id": "title", "name": "Name", "type": "title", "title": {}}}], "parent": {"type": "block_id", "block_id": "b81f8caf-3ec4-4455-9a0b-25c2bd3b60cb"}, "url": "https://www.notion.so/b75d2e55cc804afaa273c78178ac6b3f", "public_url": null, "archived": false}, "emitted_at": 1708341487319} +{"stream": "databases", "data": {"object": "database", "id": "fbff7d4e-eca4-4432-91e6-ec64ba4b5a98", "cover": null, "icon": null, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_time": "2021-10-19T13:33:00.000Z", "title": [{"type": "text", "text": {"content": "Questions", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Questions", "href": null}], "description": [], "is_inline": true, "properties": [{"name": "Difficulty", "value": {"id": "'i6%2F", "name": "Difficulty", "type": "select", "select": {"options": [{"id": "f00068b9-7612-45da-91ad-1a7b1d259375", "name": "Easy", "color": "green", "description": null}, {"id": "8e244bfe-d4c7-48c5-9088-ffd6926b4ba0", "name": "Medium", "color": "yellow", "description": null}, {"id": "9ab57ef4-eab1-4b20-a502-047610b5c97d", "name": "Hard", "color": "red", "description": null}]}}}, {"name": "Skills", "value": {"id": "K%3AtR", "name": "Skills", "type": "multi_select", "multi_select": {"options": [{"id": "72f4d134-a773-48c1-ba3d-b529f55c6818", "name": "Front end", "color": "default", "description": null}, {"id": "c20f5d57-3e35-4b39-b556-05071203cc1a", "name": "Backend", "color": "default", "description": null}, {"id": "31d5735c-d6ba-4bd7-940f-bdcb36091c02", "name": "Architecture", "color": "default", "description": null}, {"id": "0398de54-af68-4c3a-9953-3788e8eaadbf", "name": "Algorithms", "color": "default", "description": null}, {"id": "df9dff09-7dea-4409-a10f-b5e2b546ad94", "name": "Data Structures", "color": "default", "description": null}]}}}, {"name": "Question Name", "value": {"id": "title", "name": "Question Name", "type": "title", "title": {}}}], "parent": {"type": "page_id", "page_id": "4999109d-1b7b-41a2-abb4-84f6b961ee74"}, "url": "https://www.notion.so/fbff7d4eeca4443291e6ec64ba4b5a98", "public_url": null, "archived": false}, "emitted_at": 1708341487319} +{"stream": "databases", "data": {"object": "database", "id": "9b1ce91e-a93a-437c-8c92-81083cd98540", "cover": null, "icon": {"type": "emoji", "emoji": "\u270f\ufe0f"}, "created_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "ec324c09-af75-40f0-b91a-49ded74fdaf5"}, "last_edited_time": "2023-09-13T00:06:00.000Z", "title": [{"type": "text", "text": {"content": "Meeting Notes", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Meeting Notes", "href": null}], "description": [{"type": "text", "text": {"content": "Use this template to capture notes from all meetings in one accessible spot.\nNotes can be tagged by meeting type to make them easy to find. \nSee when each meeting took place and who was there.\n\n", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Use this template to capture notes from all meetings in one accessible spot.\nNotes can be tagged by meeting type to make them easy to find. \nSee when each meeting took place and who was there.\n\n", "href": null}, {"type": "text", "text": {"content": "\u2193", "link": null}, "annotations": {"bold": true, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "\u2193", "href": null}, {"type": "text", "text": {"content": " Click ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": " Click ", "href": null}, {"type": "text", "text": {"content": "List View", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": true, "color": "default"}, "plain_text": "List View", "href": null}, {"type": "text", "text": {"content": " to create and see other views, including a board organized by meeting type.", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": " to create and see other views, including a board organized by meeting type.", "href": null}], "is_inline": false, "properties": [{"name": "Last Edited Time", "value": {"id": "0AiB", "name": "Last Edited Time", "type": "last_edited_time", "last_edited_time": {}}}, {"name": "Created By", "value": {"id": "F%5D)%3F", "name": "Created By", "type": "created_by", "created_by": {}}}, {"name": "Created", "value": {"id": "Ird4", "name": "Created", "type": "created_time", "created_time": {}}}, {"name": "Type", "value": {"id": "_%7B%5C7", "name": "Type", "type": "select", "select": {"options": [{"id": "3a8fd64c-899d-4c39-ba97-ac4f565d6e94", "name": "Post-mortem", "color": "red", "description": null}, {"id": "28b68013-20d5-4824-b810-45cde8784581", "name": "Standup", "color": "green", "description": null}, {"id": "8ee247a9-cb60-430a-9ea6-d5c053253334", "name": "Weekly Sync", "color": "blue", "description": null}, {"id": "5fb57c36-999f-49e2-b153-96531d086862", "name": "Sprint Planning", "color": "yellow", "description": null}, {"id": "1747fcca-8207-42c8-802f-fd43965c016a", "name": "Ad Hoc", "color": "orange", "description": null}]}}}, {"name": "Participants", "value": {"id": "b%3AeA", "name": "Participants", "type": "people", "people": {}}}, {"name": "Name", "value": {"id": "title", "name": "Name", "type": "title", "title": {}}}], "parent": {"type": "workspace", "workspace": true}, "url": "https://www.notion.so/9b1ce91ea93a437c8c9281083cd98540", "public_url": null, "archived": false}, "emitted_at": 1708341487319} {"stream": "pages", "data": {"object": "page", "id": "39a69b4e-7cc2-4f7a-a656-dd128f3ce855", "created_time": "2021-10-19T13:33:00.000Z", "last_edited_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "cover": null, "icon": null, "parent": {"type": "database_id", "database_id": "9b1ce91e-a93a-437c-8c92-81083cd98540"}, "archived": false, "properties": [{"name": "Last Edited Time", "value": {"id": "0AiB", "type": "last_edited_time", "last_edited_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Created By", "value": {"id": "F%5D)%3F", "type": "created_by", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a", "name": "Airyte", "avatar_url": null, "type": "person", "person": {"email": "integration-test@airbyte.io"}}}}, {"name": "Created", "value": {"id": "Ird4", "type": "created_time", "created_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Type", "value": {"id": "_%7B%5C7", "type": "select", "select": {"id": "28b68013-20d5-4824-b810-45cde8784581", "name": "Standup", "color": "green"}}}, {"name": "Participants", "value": {"id": "b%3AeA", "type": "people", "people": []}}, {"name": "Name", "value": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Daily Standup", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Daily Standup", "href": null}]}}], "url": "https://www.notion.so/Daily-Standup-39a69b4e7cc24f7aa656dd128f3ce855", "public_url": null}, "emitted_at": 1697023284463} {"stream": "pages", "data": {"object": "page", "id": "621d3dc4-55fe-46ce-a3ff-83da06e5f9fb", "created_time": "2021-10-19T13:33:00.000Z", "last_edited_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "cover": null, "icon": null, "parent": {"type": "database_id", "database_id": "9b1ce91e-a93a-437c-8c92-81083cd98540"}, "archived": false, "properties": [{"name": "Last Edited Time", "value": {"id": "0AiB", "type": "last_edited_time", "last_edited_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Created By", "value": {"id": "F%5D)%3F", "type": "created_by", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a", "name": "Airyte", "avatar_url": null, "type": "person", "person": {"email": "integration-test@airbyte.io"}}}}, {"name": "Created", "value": {"id": "Ird4", "type": "created_time", "created_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Type", "value": {"id": "_%7B%5C7", "type": "select", "select": {"id": "5fb57c36-999f-49e2-b153-96531d086862", "name": "Sprint Planning", "color": "yellow"}}}, {"name": "Participants", "value": {"id": "b%3AeA", "type": "people", "people": []}}, {"name": "Name", "value": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Sprint Planning ", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Sprint Planning ", "href": null}]}}], "url": "https://www.notion.so/Sprint-Planning-621d3dc455fe46cea3ff83da06e5f9fb", "public_url": null}, "emitted_at": 1697023284465} {"stream": "pages", "data": {"object": "page", "id": "6eb2dedc-8b88-486c-8648-d1878bafb106", "created_time": "2021-10-19T13:33:00.000Z", "last_edited_time": "2021-10-19T13:33:00.000Z", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "last_edited_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a"}, "cover": null, "icon": null, "parent": {"type": "database_id", "database_id": "9b1ce91e-a93a-437c-8c92-81083cd98540"}, "archived": false, "properties": [{"name": "Last Edited Time", "value": {"id": "0AiB", "type": "last_edited_time", "last_edited_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Created By", "value": {"id": "F%5D)%3F", "type": "created_by", "created_by": {"object": "user", "id": "f5ac1fcb-a06b-4dcc-80e5-403c40dfb38a", "name": "Airyte", "avatar_url": null, "type": "person", "person": {"email": "integration-test@airbyte.io"}}}}, {"name": "Created", "value": {"id": "Ird4", "type": "created_time", "created_time": "2021-10-19T13:33:00.000Z"}}, {"name": "Type", "value": {"id": "_%7B%5C7", "type": "select", "select": {"id": "1747fcca-8207-42c8-802f-fd43965c016a", "name": "Ad Hoc", "color": "orange"}}}, {"name": "Participants", "value": {"id": "b%3AeA", "type": "people", "people": []}}, {"name": "Name", "value": {"id": "title", "type": "title", "title": [{"type": "text", "text": {"content": "Ad Hoc Meeting", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Ad Hoc Meeting", "href": null}]}}], "url": "https://www.notion.so/Ad-Hoc-Meeting-6eb2dedc8b88486c8648d1878bafb106", "public_url": null}, "emitted_at": 1697023284465} diff --git a/airbyte-integrations/connectors/source-notion/metadata.yaml b/airbyte-integrations/connectors/source-notion/metadata.yaml index 8a95d375f3cf..58b329ffe793 100644 --- a/airbyte-integrations/connectors/source-notion/metadata.yaml +++ b/airbyte-integrations/connectors/source-notion/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 6e00b415-b02e-4160-bf02-58176a0ae687 - dockerImageTag: 2.0.9 + dockerImageTag: 2.1.0 dockerRepository: airbyte/source-notion documentationUrl: https://docs.airbyte.com/integrations/sources/notion githubIssueLabel: source-notion diff --git a/airbyte-integrations/connectors/source-notion/pyproject.toml b/airbyte-integrations/connectors/source-notion/pyproject.toml index 4218b07b35ba..3c4250763099 100644 --- a/airbyte-integrations/connectors/source-notion/pyproject.toml +++ b/airbyte-integrations/connectors/source-notion/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.0.9" +version = "2.1.0" name = "source-notion" description = "Source implementation for Notion." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/rich_text.json b/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/rich_text.json index cc003048b875..e8ecf832da80 100644 --- a/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/rich_text.json +++ b/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/rich_text.json @@ -32,6 +32,17 @@ "properties": { "type": { "type": ["null", "string"] + }, + "info": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + } + } } } }, diff --git a/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/user.json b/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/user.json index d893b1147b7e..8c5000dba205 100644 --- a/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/user.json +++ b/airbyte-integrations/connectors/source-notion/source_notion/schemas/shared/user.json @@ -37,10 +37,38 @@ "type": { "type": "string" }, + "info": { + "avatar_url": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "person": { + "type": ["null", "object"], + "properties": { + "email": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } + } + } + }, "workspace": { "type": ["null", "boolean"] } } + }, + "workspace_name": { + "type": ["null", "string"] } } } diff --git a/airbyte-integrations/connectors/source-notion/source_notion/streams.py b/airbyte-integrations/connectors/source-notion/source_notion/streams.py index a0546d2116c4..f7cb9e456e25 100644 --- a/airbyte-integrations/connectors/source-notion/source_notion/streams.py +++ b/airbyte-integrations/connectors/source-notion/source_notion/streams.py @@ -252,6 +252,22 @@ def request_params(self, next_page_token: Mapping[str, Any] = None, **kwargs) -> params["start_cursor"] = next_page_token["next_cursor"] return params + def transform(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + owner = record.get("bot", {}).get("owner") + if owner: + owner_type = owner.get("type") + owner_info = owner.get(owner_type) + if owner_type and owner_info: + record["bot"]["owner"]["info"] = owner_info + del record["bot"]["owner"][owner_type] + return record + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + # sometimes notion api returns response without results object + data = response.json().get("results", []) + for record in data: + yield self.transform(record) + class Databases(IncrementalNotionStream): """ @@ -313,6 +329,20 @@ def stream_slices( yield {"page_id": page_id} + def transform(self, record: Mapping[str, Any]) -> Mapping[str, Any]: + transform_object_field = record.get("type") + + if transform_object_field: + rich_text = record.get(transform_object_field, {}).get("rich_text", []) + for r in rich_text: + mention = r.get("mention") + if mention: + type_info = mention[mention["type"]] + record[transform_object_field]["rich_text"][rich_text.index(r)]["mention"]["info"] = type_info + del record[transform_object_field]["rich_text"][rich_text.index(r)]["mention"][mention["type"]] + + return record + def parse_response(self, response: requests.Response, stream_state: Mapping[str, Any], **kwargs) -> Iterable[Mapping]: # pages and databases blocks are already fetched in their streams, so no # need to do it again @@ -321,7 +351,7 @@ def parse_response(self, response: requests.Response, stream_state: Mapping[str, records = super().parse_response(response, stream_state=stream_state, **kwargs) for record in records: if record["type"] not in ("child_page", "child_database", "ai_block"): - yield record + yield self.transform(record) def read_records(self, **kwargs) -> Iterable[Mapping[str, Any]]: # if reached recursive limit, don't read anymore diff --git a/airbyte-integrations/connectors/source-notion/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-notion/unit_tests/test_streams.py index ceeb5b1ca5cb..d369b201becc 100644 --- a/airbyte-integrations/connectors/source-notion/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-notion/unit_tests/test_streams.py @@ -312,3 +312,41 @@ def test_request_throttle(initial_page_size, expected_page_size, mock_response, stream.should_retry(response=response) assert stream.page_size == expected_page_size + + +def test_users_record_transformer(): + stream = Users(config=MagicMock()) + response_record = { + "object": "user", "id": "id", "name": "Airbyte", "avatar_url": "some url", "type": "bot", + "bot": {"owner": {"type": "user", "user": {"object": "user", "id": "id", "name": "Test User", "avatar_url": None, "type": "person", + "person": {"email": "email"}}}, "workspace_name": "test"} + } + expected_record = { + "object": "user", "id": "id", "name": "Airbyte", "avatar_url": "some url", "type": "bot", + "bot": {"owner": {"type": "user", "info": {"object": "user", "id": "id", "name": "Test User", "avatar_url": None, "type": "person", + "person": {"email": "email"}}}, "workspace_name": "test"} + } + assert stream.transform(response_record) == expected_record + + +def test_block_record_transformer(): + stream = Blocks(parent=None, config=MagicMock()) + response_record = { + "object": "block", "id": "id", "parent": {"type": "page_id", "page_id": "id"}, "created_time": "2021-10-19T13:33:00.000Z", "last_edited_time": "2021-10-19T13:33:00.000Z", + "created_by": {"object": "user", "id": "id"}, "last_edited_by": {"object": "user", "id": "id"}, "has_children": False, "archived": False, "type": "paragraph", + "paragraph": {"rich_text": [{"type": "text", "text": {"content": "test", "link": None}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, "plain_text": "test", "href": None}, + {"type": "text", "text": {"content": "@", "link": None}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": True, "color": "default"}, "plain_text": "@", "href": None}, + {"type": "text", "text": {"content": "test", "link": None}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, "plain_text": "test", "href": None}, + {"type": "mention", "mention": {"type": "page", "page": {"id": "id"}}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, + "plain_text": "test", "href": "https://www.notion.so/id"}], "color": "default"} + } + expected_record = { + "object": "block", "id": "id", "parent": {"type": "page_id", "page_id": "id"}, "created_time": "2021-10-19T13:33:00.000Z", "last_edited_time": "2021-10-19T13:33:00.000Z", + "created_by": {"object": "user", "id": "id"}, "last_edited_by": {"object": "user", "id": "id"}, "has_children": False, "archived": False, "type": "paragraph", + "paragraph": {"rich_text": [{"type": "text", "text": {"content": "test", "link": None}, "annotations":{"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, "plain_text":"test", "href": None}, + {"type": "text", "text": {"content": "@", "link": None}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": True, "color": "default"}, "plain_text": "@", "href": None}, + {"type": "text", "text": {"content": "test", "link": None}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, "plain_text": "test", "href": None}, + {"type": "mention", "mention": {"type": "page", "info": {"id": "id"}}, "annotations": {"bold": False, "italic": False, "strikethrough": False, "underline": False, "code": False, "color": "default"}, "plain_text": "test", "href": "https://www.notion.so/id"}], + "color": "default"} + } + assert stream.transform(response_record) == expected_record diff --git a/docs/integrations/sources/notion.md b/docs/integrations/sources/notion.md index 84319c018bc9..04d96e2a9be2 100644 --- a/docs/integrations/sources/notion.md +++ b/docs/integrations/sources/notion.md @@ -110,43 +110,44 @@ The connector is restricted by Notion [request limits](https://developers.notion ## Changelog -| Version | Date | Pull Request | Subject | -| :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------- | -| 2.0.9 | 2024-02-12 | [35155](https://github.com/airbytehq/airbyte/pull/35155) | Manage dependencies with Poetry. | -| 2.0.8 | 2023-11-01 | [31899](https://github.com/airbytehq/airbyte/pull/31899) | Fix `table_row.cells` property in `Blocks` stream | -| 2.0.7 | 2023-10-31 | [32004](https://github.com/airtybehq/airbyte/pull/32004) | Reduce page_size on 504 errors | -| 2.0.6 | 2023-10-25 | [31825](https://github.com/airbytehq/airbyte/pull/31825) | Increase max_retries on retryable errors | -| 2.0.5 | 2023-10-23 | [31742](https://github.com/airbytehq/airbyte/pull/31742) | Add 'synced_block' property to Blocks schema | -| 2.0.4 | 2023-10-19 | [31625](https://github.com/airbytehq/airbyte/pull/31625) | Fix check_connection method | -| 2.0.3 | 2023-10-19 | [31612](https://github.com/airbytehq/airbyte/pull/31612) | Add exponential backoff for 500 errors | -| 2.0.2 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image | -| 2.0.1 | 2023-10-17 | [31507](https://github.com/airbytehq/airbyte/pull/31507) | Add start_date validation checks | -| 2.0.0 | 2023-10-09 | [30587](https://github.com/airbytehq/airbyte/pull/30587) | Source-wide schema update | -| 1.3.0 | 2023-10-09 | [30324](https://github.com/airbytehq/airbyte/pull/30324) | Add `Comments` stream | -| 1.2.2 | 2023-10-09 | [30780](https://github.com/airbytehq/airbyte/pull/30780) | Update Start Date in config to optional field | -| 1.2.1 | 2023-10-08 | [30750](https://github.com/airbytehq/airbyte/pull/30750) | Add availability strategy | -| 1.2.0 | 2023-10-04 | [31053](https://github.com/airbytehq/airbyte/pull/31053) | Add undeclared fields for blocks and pages streams | -| 1.1.2 | 2023-08-30 | [29999](https://github.com/airbytehq/airbyte/pull/29999) | Update error handling during connection check | -| 1.1.1 | 2023-06-14 | [26535](https://github.com/airbytehq/airbyte/pull/26535) | Migrate from deprecated `authSpecification` to `advancedAuth` | -| 1.1.0 | 2023-06-08 | [27170](https://github.com/airbytehq/airbyte/pull/27170) | Fix typo in `blocks` schema | -| 1.0.9 | 2023-06-08 | [27062](https://github.com/airbytehq/airbyte/pull/27062) | Skip streams with `invalid_start_cursor` error | -| 1.0.8 | 2023-06-07 | [27073](https://github.com/airbytehq/airbyte/pull/27073) | Add empty results handling for stream `Blocks` | -| 1.0.7 | 2023-06-06 | [27060](https://github.com/airbytehq/airbyte/pull/27060) | Add skipping 404 error in `Blocks` stream | -| 1.0.6 | 2023-05-18 | [26286](https://github.com/airbytehq/airbyte/pull/26286) | Add `parent` field to `Blocks` stream | -| 1.0.5 | 2023-05-01 | [25709](https://github.com/airbytehq/airbyte/pull/25709) | Fixed `ai_block is unsupported by API` issue, while fetching `Blocks` stream | -| 1.0.4 | 2023-04-11 | [25041](https://github.com/airbytehq/airbyte/pull/25041) | Improve error handling for API /search | -| 1.0.3 | 2023-03-02 | [22931](https://github.com/airbytehq/airbyte/pull/22931) | Specified date formatting in specification | -| 1.0.2 | 2023-02-24 | [23437](https://github.com/airbytehq/airbyte/pull/23437) | Add retry for 400 error (validation_error) | -| 1.0.1 | 2023-01-27 | [22018](https://github.com/airbytehq/airbyte/pull/22018) | Set `AvailabilityStrategy` for streams explicitly to `None` | -| 1.0.0 | 2022-12-19 | [20639](https://github.com/airbytehq/airbyte/pull/20639) | Fix `Pages` stream schema | -| 0.1.10 | 2022-09-28 | [17298](https://github.com/airbytehq/airbyte/pull/17298) | Use "Retry-After" header for backoff | -| 0.1.9 | 2022-09-16 | [16799](https://github.com/airbytehq/airbyte/pull/16799) | Migrate to per-stream state | -| 0.1.8 | 2022-09-05 | [16272](https://github.com/airbytehq/airbyte/pull/16272) | Update spec description to include working timestamp example | -| 0.1.7 | 2022-07-26 | [15042](https://github.com/airbytehq/airbyte/pull/15042) | Update `additionalProperties` field to true from shared schemas | -| 0.1.6 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from schemas and spec | -| 0.1.5 | 2022-07-14 | [14706](https://github.com/airbytehq/airbyte/pull/14706) | Added OAuth2.0 authentication | -| 0.1.4 | 2022-07-07 | [14505](https://github.com/airbytehq/airbyte/pull/14505) | Fixed bug when normalization didn't run through | -| 0.1.3 | 2022-04-22 | [11452](https://github.com/airbytehq/airbyte/pull/11452) | Use pagination for User stream | -| 0.1.2 | 2022-01-11 | [9084](https://github.com/airbytehq/airbyte/pull/9084) | Fix documentation URL | -| 0.1.1 | 2021-12-30 | [9207](https://github.com/airbytehq/airbyte/pull/9207) | Update connector fields title/description | -| 0.1.0 | 2021-10-17 | [7092](https://github.com/airbytehq/airbyte/pull/7092) | Initial Release | +| Version | Date | Pull Request | Subject | +|:--------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------| +| 2.1.0 | 2024-02-19 | [35409](https://github.com/airbytehq/airbyte/pull/35409) | Update users stream schema with bot type info fields and block schema with mention type info fields. | +| 2.0.9 | 2024-02-12 | [35155](https://github.com/airbytehq/airbyte/pull/35155) | Manage dependencies with Poetry. | +| 2.0.8 | 2023-11-01 | [31899](https://github.com/airbytehq/airbyte/pull/31899) | Fix `table_row.cells` property in `Blocks` stream | +| 2.0.7 | 2023-10-31 | [32004](https://github.com/airtybehq/airbyte/pull/32004) | Reduce page_size on 504 errors | +| 2.0.6 | 2023-10-25 | [31825](https://github.com/airbytehq/airbyte/pull/31825) | Increase max_retries on retryable errors | +| 2.0.5 | 2023-10-23 | [31742](https://github.com/airbytehq/airbyte/pull/31742) | Add 'synced_block' property to Blocks schema | +| 2.0.4 | 2023-10-19 | [31625](https://github.com/airbytehq/airbyte/pull/31625) | Fix check_connection method | +| 2.0.3 | 2023-10-19 | [31612](https://github.com/airbytehq/airbyte/pull/31612) | Add exponential backoff for 500 errors | +| 2.0.2 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image | +| 2.0.1 | 2023-10-17 | [31507](https://github.com/airbytehq/airbyte/pull/31507) | Add start_date validation checks | +| 2.0.0 | 2023-10-09 | [30587](https://github.com/airbytehq/airbyte/pull/30587) | Source-wide schema update | +| 1.3.0 | 2023-10-09 | [30324](https://github.com/airbytehq/airbyte/pull/30324) | Add `Comments` stream | +| 1.2.2 | 2023-10-09 | [30780](https://github.com/airbytehq/airbyte/pull/30780) | Update Start Date in config to optional field | +| 1.2.1 | 2023-10-08 | [30750](https://github.com/airbytehq/airbyte/pull/30750) | Add availability strategy | +| 1.2.0 | 2023-10-04 | [31053](https://github.com/airbytehq/airbyte/pull/31053) | Add undeclared fields for blocks and pages streams | +| 1.1.2 | 2023-08-30 | [29999](https://github.com/airbytehq/airbyte/pull/29999) | Update error handling during connection check | +| 1.1.1 | 2023-06-14 | [26535](https://github.com/airbytehq/airbyte/pull/26535) | Migrate from deprecated `authSpecification` to `advancedAuth` | +| 1.1.0 | 2023-06-08 | [27170](https://github.com/airbytehq/airbyte/pull/27170) | Fix typo in `blocks` schema | +| 1.0.9 | 2023-06-08 | [27062](https://github.com/airbytehq/airbyte/pull/27062) | Skip streams with `invalid_start_cursor` error | +| 1.0.8 | 2023-06-07 | [27073](https://github.com/airbytehq/airbyte/pull/27073) | Add empty results handling for stream `Blocks` | +| 1.0.7 | 2023-06-06 | [27060](https://github.com/airbytehq/airbyte/pull/27060) | Add skipping 404 error in `Blocks` stream | +| 1.0.6 | 2023-05-18 | [26286](https://github.com/airbytehq/airbyte/pull/26286) | Add `parent` field to `Blocks` stream | +| 1.0.5 | 2023-05-01 | [25709](https://github.com/airbytehq/airbyte/pull/25709) | Fixed `ai_block is unsupported by API` issue, while fetching `Blocks` stream | +| 1.0.4 | 2023-04-11 | [25041](https://github.com/airbytehq/airbyte/pull/25041) | Improve error handling for API /search | +| 1.0.3 | 2023-03-02 | [22931](https://github.com/airbytehq/airbyte/pull/22931) | Specified date formatting in specification | +| 1.0.2 | 2023-02-24 | [23437](https://github.com/airbytehq/airbyte/pull/23437) | Add retry for 400 error (validation_error) | +| 1.0.1 | 2023-01-27 | [22018](https://github.com/airbytehq/airbyte/pull/22018) | Set `AvailabilityStrategy` for streams explicitly to `None` | +| 1.0.0 | 2022-12-19 | [20639](https://github.com/airbytehq/airbyte/pull/20639) | Fix `Pages` stream schema | +| 0.1.10 | 2022-09-28 | [17298](https://github.com/airbytehq/airbyte/pull/17298) | Use "Retry-After" header for backoff | +| 0.1.9 | 2022-09-16 | [16799](https://github.com/airbytehq/airbyte/pull/16799) | Migrate to per-stream state | +| 0.1.8 | 2022-09-05 | [16272](https://github.com/airbytehq/airbyte/pull/16272) | Update spec description to include working timestamp example | +| 0.1.7 | 2022-07-26 | [15042](https://github.com/airbytehq/airbyte/pull/15042) | Update `additionalProperties` field to true from shared schemas | +| 0.1.6 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from schemas and spec | +| 0.1.5 | 2022-07-14 | [14706](https://github.com/airbytehq/airbyte/pull/14706) | Added OAuth2.0 authentication | +| 0.1.4 | 2022-07-07 | [14505](https://github.com/airbytehq/airbyte/pull/14505) | Fixed bug when normalization didn't run through | +| 0.1.3 | 2022-04-22 | [11452](https://github.com/airbytehq/airbyte/pull/11452) | Use pagination for User stream | +| 0.1.2 | 2022-01-11 | [9084](https://github.com/airbytehq/airbyte/pull/9084) | Fix documentation URL | +| 0.1.1 | 2021-12-30 | [9207](https://github.com/airbytehq/airbyte/pull/9207) | Update connector fields title/description | +| 0.1.0 | 2021-10-17 | [7092](https://github.com/airbytehq/airbyte/pull/7092) | Initial Release | From 2458c9b7b442390535e1da17fa9191b2d91f73e5 Mon Sep 17 00:00:00 2001 From: Augustin Date: Thu, 22 Feb 2024 13:16:50 +0100 Subject: [PATCH 14/74] airbyte-ci: make QA check work on strict-encrypt connectors (#35536) --- airbyte-ci/connectors/pipelines/README.md | 1 + .../connectors/test/steps/common.py | 30 +++++++++++++++---- .../connectors/pipelines/pyproject.toml | 2 +- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/airbyte-ci/connectors/pipelines/README.md b/airbyte-ci/connectors/pipelines/README.md index cf44ae7a4843..e63b59c46136 100644 --- a/airbyte-ci/connectors/pipelines/README.md +++ b/airbyte-ci/connectors/pipelines/README.md @@ -644,6 +644,7 @@ E.G.: running Poe tasks on the modified internal packages of the current branch: | Version | PR | Description | | ------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | | 4.3.1 | [#35437](https://github.com/airbytehq/airbyte/pull/35437) | Do not run QA checks on publish, just MetadataValidation. | | 4.3.0 | [#35438](https://github.com/airbytehq/airbyte/pull/35438) | Optionally disable telemetry with environment variable. | | 4.2.4 | [#35325](https://github.com/airbytehq/airbyte/pull/35325) | Use `connectors_qa` for QA checks and remove redundant checks. | diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py index 313bb09d69e6..177c7dc6a281 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py @@ -8,6 +8,7 @@ import os from abc import ABC, abstractmethod from functools import cached_property +from pathlib import Path from typing import ClassVar, List, Optional import requests # type: ignore @@ -124,16 +125,33 @@ class QaChecks(SimpleDockerStep): """ def __init__(self, context: ConnectorContext) -> None: + code_directory = context.connector.code_directory + documentation_file_path = context.connector.documentation_file_path + migration_guide_file_path = context.connector.migration_guide_file_path + icon_path = context.connector.icon_path + technical_name = context.connector.technical_name + + # When the connector is strict-encrypt, we should run QA checks on the main one as it's the one whose artifacts gets released + if context.connector.technical_name.endswith("-strict-encrypt"): + technical_name = technical_name.replace("-strict-encrypt", "") + code_directory = Path(str(code_directory).replace("-strict-encrypt", "")) + if documentation_file_path: + documentation_file_path = Path(str(documentation_file_path).replace("-strict-encrypt", "")) + if migration_guide_file_path: + migration_guide_file_path = Path(str(migration_guide_file_path).replace("-strict-encrypt", "")) + if icon_path: + icon_path = Path(str(icon_path).replace("-strict-encrypt", "")) + super().__init__( - title=f"Run QA checks for {context.connector.technical_name}", + title=f"Run QA checks for {technical_name}", context=context, paths_to_mount=[ - MountPath(context.connector.code_directory), + MountPath(code_directory), # These paths are optional # But their absence might make the QA check fail - MountPath(context.connector.documentation_file_path, optional=True), - MountPath(context.connector.migration_guide_file_path, optional=True), - MountPath(context.connector.icon_path, optional=True), + MountPath(documentation_file_path, optional=True), + MountPath(migration_guide_file_path, optional=True), + MountPath(icon_path, optional=True), ], internal_tools=[ MountPath(INTERNAL_TOOL_PATHS.CONNECTORS_QA.value), @@ -146,7 +164,7 @@ def __init__(self, context: ConnectorContext) -> None: }.items() if v }, - command=["connectors-qa", "run", f"--name={context.connector.technical_name}"], + command=["connectors-qa", "run", f"--name={technical_name}"], ) diff --git a/airbyte-ci/connectors/pipelines/pyproject.toml b/airbyte-ci/connectors/pipelines/pyproject.toml index 4c6158f82964..d6cca9affdc0 100644 --- a/airbyte-ci/connectors/pipelines/pyproject.toml +++ b/airbyte-ci/connectors/pipelines/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "pipelines" -version = "4.3.1" +version = "4.3.2" description = "Packaged maintained by the connector operations team to perform CI for connectors' pipelines" authors = ["Airbyte "] From 943785eca80f07d09aa5c35bc129634201559d84 Mon Sep 17 00:00:00 2001 From: Evan Tahler Date: Thu, 22 Feb 2024 06:20:28 -0800 Subject: [PATCH 15/74] Update docs to show archived information if connector is not in registries (#35468) --- .../src/components/ConnectorRegistry.jsx | 13 +++- .../src/components/HeaderDecoration.jsx | 19 +++--- docusaurus/src/remark/utils.js | 61 ++++++++++++++----- 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/docusaurus/src/components/ConnectorRegistry.jsx b/docusaurus/src/components/ConnectorRegistry.jsx index 1766c204eddf..079acedaa99d 100644 --- a/docusaurus/src/components/ConnectorRegistry.jsx +++ b/docusaurus/src/components/ConnectorRegistry.jsx @@ -42,7 +42,8 @@ export default function ConnectorRegistry({ type }) { const connectors = registry .filter((c) => c.connector_type === type) - .filter((c) => c.name_oss); + .filter((c) => c.name_oss) + .filter((c) => c.supportLevel_oss); // at lease one connector is missing a support level return (
@@ -77,8 +78,14 @@ export default function ConnectorRegistry({ type }) { {/* min width to prevent wrapping */} 📕 - ⚙️ - 🐛 + {connector.supportLevel_oss != "archived" ? ( + ⚙️ + ) : ( + "" + )} + {connector.supportLevel_oss != "archived" ? ( + 🐛 + ) : null} {connector.supportLevel_oss} diff --git a/docusaurus/src/components/HeaderDecoration.jsx b/docusaurus/src/components/HeaderDecoration.jsx index 9d23dcf77a86..01f43e5570cb 100644 --- a/docusaurus/src/components/HeaderDecoration.jsx +++ b/docusaurus/src/components/HeaderDecoration.jsx @@ -67,14 +67,17 @@ export const HeaderDecoration = ({
-
-
Latest Version
-
- - {dockerImageTag} - -
-
+ {supportLevel !== "archived" && ( +
+
Latest Version
+ +
+ + {dockerImageTag} + +
+
+ )}
diff --git a/docusaurus/src/remark/utils.js b/docusaurus/src/remark/utils.js index f946396ce7f1..e28710264693 100644 --- a/docusaurus/src/remark/utils.js +++ b/docusaurus/src/remark/utils.js @@ -16,19 +16,52 @@ const isDocsPage = (vfile) => { }; const getRegistryEntry = async (vfile) => { - const pathParts = vfile.path.split("/"); - const connectorName = pathParts.pop().split(".")[0]; - const connectorType = pathParts.pop(); - const dockerRepository = `airbyte/${connectorType.replace( - /s$/, - "" - )}-${connectorName}`; - - const registry = await catalog; - - return registry.find( - (r) => r.dockerRepository_oss === dockerRepository + const pathParts = vfile.path.split("/"); + const connectorName = pathParts.pop().split(".")[0]; + const connectorType = pathParts.pop(); + const dockerRepository = `airbyte/${connectorType.replace( + /s$/, + "" + )}-${connectorName}`; + + const registry = await catalog; + + let registryEntry = registry.find( + (r) => r.dockerRepository_oss === dockerRepository + ); + + if (!registryEntry) { + registryEntry = buildArchivedRegistryEntry( + connectorName, + dockerRepository, + connectorType ); -} + } + + return registryEntry; +}; + +const buildArchivedRegistryEntry = ( + connectorName, + dockerRepository, + connectorType +) => { + const dockerName = dockerRepository.split("/")[1]; + const registryEntry = { + connectorName, + name_oss: dockerName, + dockerRepository_oss: dockerRepository, + is_oss: false, + is_cloud: false, + iconUrl_oss: `https://connectors.airbyte.com/files/metadata/airbyte/${dockerName}/latest/icon.svg`, + supportLevel_oss: "archived", + documentationUrl_oss: `https://docs.airbyte.com/integrations/${connectorType}s/${connectorName}`, + }; -module.exports = { isDocsPage, getRegistryEntry }; + return registryEntry; +}; + +module.exports = { + isDocsPage, + getRegistryEntry, +}; From a086e38194a8b6d6343f47b1e4f1c719e54f8bcf Mon Sep 17 00:00:00 2001 From: Anatolii Yatsuk <35109939+tolik0@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:01:56 +0200 Subject: [PATCH 16/74] :bug: Source Facebook Marketing: Add missing config migration (#35539) --- .../connectors/source-facebook-marketing/metadata.yaml | 2 +- .../connectors/source-facebook-marketing/pyproject.toml | 2 +- .../source-facebook-marketing/source_facebook_marketing/run.py | 3 ++- docs/integrations/sources/facebook-marketing.md | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/airbyte-integrations/connectors/source-facebook-marketing/metadata.yaml b/airbyte-integrations/connectors/source-facebook-marketing/metadata.yaml index 2c989286b785..4f3f93f23537 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/metadata.yaml +++ b/airbyte-integrations/connectors/source-facebook-marketing/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: e7778cfc-e97c-4458-9ecb-b4f2bba8946c - dockerImageTag: 1.4.1 + dockerImageTag: 1.4.2 dockerRepository: airbyte/source-facebook-marketing documentationUrl: https://docs.airbyte.com/integrations/sources/facebook-marketing githubIssueLabel: source-facebook-marketing diff --git a/airbyte-integrations/connectors/source-facebook-marketing/pyproject.toml b/airbyte-integrations/connectors/source-facebook-marketing/pyproject.toml index 7d7bd3063ddf..04043b38a353 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/pyproject.toml +++ b/airbyte-integrations/connectors/source-facebook-marketing/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "1.4.1" +version = "1.4.2" name = "source-facebook-marketing" description = "Source implementation for Facebook Marketing." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/run.py b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/run.py index 2e92663e42fd..b070561488f0 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/run.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/run.py @@ -7,11 +7,12 @@ from airbyte_cdk.entrypoint import launch -from .config_migrations import MigrateAccountIdToArray +from .config_migrations import MigrateAccountIdToArray, MigrateIncludeDeletedToStatusFilters from .source import SourceFacebookMarketing def run(): source = SourceFacebookMarketing() MigrateAccountIdToArray.migrate(sys.argv[1:], source) + MigrateIncludeDeletedToStatusFilters.migrate(sys.argv[1:], source) launch(source, sys.argv[1:]) diff --git a/docs/integrations/sources/facebook-marketing.md b/docs/integrations/sources/facebook-marketing.md index 694fe73553e1..df8eafd7c64e 100644 --- a/docs/integrations/sources/facebook-marketing.md +++ b/docs/integrations/sources/facebook-marketing.md @@ -200,6 +200,7 @@ The Facebook Marketing connector uses the `lookback_window` parameter to repeate | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.4.2 | 2024-02-22 | [35539](https://github.com/airbytehq/airbyte/pull/35539) | Add missing config migration from `include_deleted` field | | 1.4.1 | 2024-02-21 | [35467](https://github.com/airbytehq/airbyte/pull/35467) | Fix error with incorrect state transforming in the 1.4.0 version | | 1.4.0 | 2024-02-20 | [32449](https://github.com/airbytehq/airbyte/pull/32449) | Replace "Include Deleted Campaigns, Ads, and AdSets" option in configuration with specific statuses selection per stream | | 1.3.3 | 2024-02-15 | [35061](https://github.com/airbytehq/airbyte/pull/35061) | Add integration tests | | From 571d13a73644be2721919e503449840eeb36a788 Mon Sep 17 00:00:00 2001 From: perangel Date: Thu, 22 Feb 2024 10:33:35 -0500 Subject: [PATCH 17/74] docs: update ALB configuration docs for exposing API (#35520) --- docs/enterprise-setup/implementation-guide.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/enterprise-setup/implementation-guide.md b/docs/enterprise-setup/implementation-guide.md index 09bcbe673eec..5a41b8086f48 100644 --- a/docs/enterprise-setup/implementation-guide.md +++ b/docs/enterprise-setup/implementation-guide.md @@ -293,6 +293,14 @@ spec: number: # service port, example: 8180 path: /auth pathType: Prefix + - backend: + service: + # format is ${RELEASE_NAME}-airbyte-api-server-svc + name: airbyte-pro-airbyte-api-server-svc + port: + number: # service port, example: 8180 + path: /v1 + pathType: Prefix ``` @@ -338,6 +346,14 @@ spec: number: 8180 path: /auth pathType: Prefix + - backend: + service: + # format is ${RELEASE_NAME}-airbyte-api-server-svc + name: airbyte-pro-airbyte-api-server-svc + port: + number: # service port, example: 8180 + path: /v1 + pathType: Prefix ``` The ALB controller will use a `ServiceAccount` that requires the [following IAM policy](https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json) to be attached. From c06bd99dce9e9dbee462da7e72ea5bf5d9d11f7b Mon Sep 17 00:00:00 2001 From: perangel Date: Thu, 22 Feb 2024 11:12:57 -0500 Subject: [PATCH 18/74] chore: remove upgrading-airbyte.md (#35545) --- .bumpversion.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 180a6df594a4..eb788944a59f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -10,6 +10,4 @@ serialize = [bumpversion:file:gradle.properties] -[bumpversion:file:docs/operator-guides/upgrading-airbyte.md] - [bumpversion:file:run-ab-platform.sh] From c2cf962ccf70a2f7a57c282592af6559a17fc42a Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 22 Feb 2024 08:37:49 -0800 Subject: [PATCH 19/74] =?UTF-8?q?=F0=9F=93=9A=20Add=20documentation=20for?= =?UTF-8?q?=20Entra=20ID=20(#34569)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sso-providers/azure-entra-id.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/access-management/sso-providers/azure-entra-id.md diff --git a/docs/access-management/sso-providers/azure-entra-id.md b/docs/access-management/sso-providers/azure-entra-id.md new file mode 100644 index 000000000000..611aad0b3cb3 --- /dev/null +++ b/docs/access-management/sso-providers/azure-entra-id.md @@ -0,0 +1,58 @@ +--- +sidebar_label: Azure Entra ID +products: cloud-teams +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Setup Single Sign-On via Azure Entra ID + +This page guides you through setting up [Single Sign-On](../sso.md) with Airbyte using **Microsoft Azure Entra ID** (formerly known as **Azure Active Directory**). + +Airbyte will communicate with your Entra ID using OpenID Connect (OIDC). + +## Creating an Entra ID app for Airbyte + +:::info +The following steps need to be executed by an administrator of your company's Azure Entra ID account. +::: + +You'll require to know your **Company Identifier** to create your application. You receive this +from your contact at Airbyte. + +### Create application + +You will need to create a new Entra ID application for Airbyte. Log into the [Azure Portal](https://portal.azure.com/) and search for the Entra ID service. + +On the Overview of Entra ID press **Add** > **App registration** on the top of the screen. + +Specify any name you want (e.g. "Airbyte") and configure a **Redirect URI** of type **Web** with the following value: + +``` +https://cloud.airbyte.com/auth/realms//broker/default/endpoint +``` + +Hit **Register** to create the application. + +### Create Client credentials + +To create Client credentials for Airbyte to talk to your application head to **Certificates & Secrets** on the detail screen of your application and select the **Client secrets** tab. + +Click **New client secret**, specify any Description you want and any Expire date you want. + +:::tip +We recommend to chose an expiry date of at least 12 months. You'll need to pass the new Client Secret to use every time the old one expires, to continue being able to log in via Entra ID. +::: + +Copy the **Value** (the Client Secret itself) immediately after creation. You won't be able to view this later on again. + +### Setup information needed + +You'll need to pass your Airbyte contact the following information of the created application. + +* **Client Secret**: as copied above +* **Application (client) ID**: You'll find this in the **Essentials** section on the **Overview** page of the application you created +* **OpenID Connect metadata document**: You'll find this in the **Endpoints** panel, that you can open from the top bar on the **Overview** page + +Once we've received this information from you, We'll setup SSO for you and let you know once it's ready to be used. From 9bc72f058b2bf34b93b62df1f54542c91a2eddef Mon Sep 17 00:00:00 2001 From: bgroff Date: Thu, 22 Feb 2024 16:46:34 +0000 Subject: [PATCH 20/74] Bump Airbyte version from 0.50.50 to 0.50.51 --- .bumpversion.cfg | 2 +- gradle.properties | 2 +- run-ab-platform.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index eb788944a59f..edace9078bfd 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.50.50 +current_version = 0.50.51 commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-[a-z]+)? diff --git a/gradle.properties b/gradle.properties index 208b1243000e..948e1c94d8d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION=0.50.50 +VERSION=0.50.51 # NOTE: some of these values are overwritten in CI! # NOTE: if you want to override this for your local machine, set overrides in ~/.gradle/gradle.properties diff --git a/run-ab-platform.sh b/run-ab-platform.sh index 5777c8132cd1..ec4b23527199 100755 --- a/run-ab-platform.sh +++ b/run-ab-platform.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION=0.50.50 +VERSION=0.50.51 # Run away from anything even a little scary set -o nounset # -u exit if a variable is not set set -o errexit # -f exit for any command failure" From 757a42a5d7bd796cbcdc1a5accc2fcfc5b62cc66 Mon Sep 17 00:00:00 2001 From: Augustin Date: Thu, 22 Feb 2024 17:49:15 +0100 Subject: [PATCH 21/74] gradle.yml: use a smaller runner (#35547) --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9f7837c6617b..cc42ba2acbb4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -25,7 +25,7 @@ jobs: # We therefore run this on a machine with a maximum number of cores. # We pay per time and per core, so there should be little difference in total cost. # The latency overhead of setting up gradle prior to running the actual task adds up to about a minute. - runs-on: connector-test-xxlarge + runs-on: connector-test-large name: Gradle Check timeout-minutes: 30 steps: From e9ccc10461a28e6adacae0d31270ed25ae27875f Mon Sep 17 00:00:00 2001 From: Stephane Geneix <147216312+stephane-airbyte@users.noreply.github.com> Date: Thu, 22 Feb 2024 09:04:02 -0800 Subject: [PATCH 22/74] airbyte-ci: augment the report for java connectors (#35317) Today we're missing the logs (both JVM and container logs) in java connector reports. This is creating a link to test artifacts. In the CI, the link will point to a zip file, while on a local run, it will point to a directory. In addition, we recently added the junit XML inlined with the test standard output and error, but that didn't really work as well as we'd hoped: The reports were slow to load, they were not ordered by time, the corresponding logs were lacking. There's still a possibility they'll be useful, so rather than removing them altogether, they will be bundled in the log zip (or directory). I'm also adding a button to copy the standard output or the standard error from a step into the clipboard. Finally, I'm reducing the max vertical size of an expanded step, so it doesn't go over 70%, which seems much cleaner to me. Here's an example of the result (from the child PR): https://storage.cloud.google.com/airbyte-ci-reports-multi/airbyte-ci/connectors/test/pull_request/stephane_02-09-add_background_thread_to_track_mssql_container_status/1708056420/d4683bfb7f90675c6b9e7c6d4bbad3f98c7a7550/source-mssql/3.7.0/output.html --- .../src/main/resources/log4j2-test.xml | 3 +- airbyte-ci/connectors/pipelines/README.md | 3 +- .../connectors/build_image/steps/__init__.py | 2 +- .../connectors/build_image/steps/common.py | 2 +- .../build_image/steps/java_connectors.py | 2 +- .../build_image/steps/normalization.py | 2 +- .../connectors/bump_version/pipeline.py | 14 +- .../migrate_to_base_image/pipeline.py | 24 +-- .../airbyte_ci/connectors/publish/pipeline.py | 2 +- .../airbyte_ci/connectors/reports.py | 67 ++++++-- .../connectors/test/steps/java_connectors.py | 14 +- .../test/steps/python_connectors.py | 10 +- .../test/steps/templates/test_report.html.j2 | 26 ++- .../connectors/upgrade_cdk/pipeline.py | 4 +- .../airbyte_ci/format/format_command.py | 6 +- .../pipelines/airbyte_ci/steps/gradle.py | 157 +++++++++--------- .../pipelines/pipelines/helpers/utils.py | 23 ++- .../pipelines/pipelines/models/artifacts.py | 47 ++++++ .../pipelines/pipelines/models/reports.py | 92 +++++----- .../pipelines/pipelines/models/steps.py | 8 +- .../connectors/pipelines/pyproject.toml | 2 +- .../connectors/pipelines/tests/test_bases.py | 2 +- .../test_python_connectors.py | 8 +- .../test_execution/test_run_steps.py | 16 +- .../pipelines/tests/test_publish.py | 4 +- .../test_tests/test_python_connectors.py | 8 +- 26 files changed, 339 insertions(+), 209 deletions(-) create mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py diff --git a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/resources/log4j2-test.xml b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/resources/log4j2-test.xml index 5fa11880cfba..9c9e72c2c33f 100644 --- a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/resources/log4j2-test.xml +++ b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/resources/log4j2-test.xml @@ -7,8 +7,7 @@ %d{yyyy-MM-dd'T'HH:mm:ss,SSS}{GMT+0}`%replace{%X{log_source}}{^ -}{} > %replace{%m}{$${env:LOG_SCRUB_PATTERN:-\*\*\*\*\*}}{*****}%n ${sys:LOG_LEVEL:-${env:LOG_LEVEL:-INFO}} - ${env:AIRBYTE_LOG_SUBDIR:-${date:yyyy-MM-dd'T'HH:mm:ss}} - build/test-logs/${logSubDir} + build/test-logs/${date:yyyy-MM-dd'T'HH:mm:ss} diff --git a/airbyte-ci/connectors/pipelines/README.md b/airbyte-ci/connectors/pipelines/README.md index e63b59c46136..7d92fc08cad2 100644 --- a/airbyte-ci/connectors/pipelines/README.md +++ b/airbyte-ci/connectors/pipelines/README.md @@ -644,7 +644,8 @@ E.G.: running Poe tasks on the modified internal packages of the current branch: | Version | PR | Description | | ------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | +| 4.4.0 | [#35317](https://github.com/airbytehq/airbyte/pull/35317) | Augment java connector reports to include full logs and junit test results | +| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | | 4.3.1 | [#35437](https://github.com/airbytehq/airbyte/pull/35437) | Do not run QA checks on publish, just MetadataValidation. | | 4.3.0 | [#35438](https://github.com/airbytehq/airbyte/pull/35438) | Optionally disable telemetry with environment variable. | | 4.2.4 | [#35325](https://github.com/airbytehq/airbyte/pull/35325) | Use `connectors_qa` for QA checks and remove redundant checks. | diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py index 7a47568639a6..712062361242 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py @@ -47,7 +47,7 @@ async def run_connector_build_pipeline(context: ConnectorContext, semaphore: any async with semaphore: async with context: build_result = await run_connector_build(context) - per_platform_built_containers = build_result.output_artifact + per_platform_built_containers = build_result.output step_results.append(build_result) if context.is_local and build_result.status is StepStatus.SUCCESS: load_image_result = await LoadContainerToLocalDockerHost(context, per_platform_built_containers, image_tag).run() diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py index 687b566f8fa5..f7ae65bffcfc 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py @@ -48,7 +48,7 @@ async def _run(self, *args: Any) -> StepResult: f"The {self.context.connector.technical_name} docker image " f"was successfully built for platform(s) {', '.join(self.build_platforms)}" ) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=success_message, output_artifact=build_results_per_platform) + return StepResult(step=self, status=StepStatus.SUCCESS, stdout=success_message, output=build_results_per_platform) async def _build_connector(self, platform: Platform, *args: Any, **kwargs: Any) -> Container: """Implement the generation of the image for the platform and return the corresponding container. diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py index aa0b3448ba68..8d31bd5a714a 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py @@ -59,7 +59,7 @@ async def run_connector_build(context: ConnectorContext) -> StepResult: build_connector_tar_result = await BuildConnectorDistributionTar(context).run() if build_connector_tar_result.status is not StepStatus.SUCCESS: return build_connector_tar_result - dist_dir = await build_connector_tar_result.output_artifact.directory(dist_tar_directory_path(context)) + dist_dir = await build_connector_tar_result.output.directory(dist_tar_directory_path(context)) return await BuildConnectorImages(context).run(dist_dir) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py index 0ac35aab7fa4..7a3bae6d0ac3 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py @@ -36,4 +36,4 @@ async def _run(self) -> StepResult: build_normalization_container = normalization.with_normalization(self.context, self.build_platform) else: build_normalization_container = self.context.dagger_client.container().from_(self.normalization_image) - return StepResult(step=self, status=StepStatus.SUCCESS, output_artifact=build_normalization_container) + return StepResult(step=self, status=StepStatus.SUCCESS, output=build_normalization_container) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py index 7b2fda58b3d5..329da37639b3 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py @@ -55,7 +55,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Connector does not have a documentation file.", - output_artifact=self.repo_dir, + output=self.repo_dir, ) try: updated_doc = self.add_changelog_entry(doc_path.read_text()) @@ -64,14 +64,14 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.FAILURE, stdout=f"Could not add changelog entry: {e}", - output_artifact=self.repo_dir, + output=self.repo_dir, ) updated_repo_dir = self.repo_dir.with_new_file(str(doc_path), contents=updated_doc) return StepResult( step=self, status=StepStatus.SUCCESS, stdout=f"Added changelog entry to {doc_path}", - output_artifact=updated_repo_dir, + output=updated_repo_dir, ) def find_line_index_for_new_entry(self, markdown_text: str) -> int: @@ -118,7 +118,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Can't retrieve the connector current version.", - output_artifact=self.repo_dir, + output=self.repo_dir, ) updated_metadata_str = self.get_metadata_with_bumped_version(current_version, self.new_version, current_metadata_str) repo_dir_with_updated_metadata = metadata_change_helpers.get_repo_dir_with_updated_metadata_str( @@ -134,7 +134,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SUCCESS, stdout=f"Updated dockerImageTag from {current_version} to {self.new_version} in {metadata_path}", - output_artifact=repo_dir_with_updated_metadata, + output=repo_dir_with_updated_metadata, ) @@ -164,7 +164,7 @@ async def run_connector_version_bump_pipeline( new_version, ) update_docker_image_tag_in_metadata_result = await update_docker_image_tag_in_metadata.run() - repo_dir_with_updated_metadata = update_docker_image_tag_in_metadata_result.output_artifact + repo_dir_with_updated_metadata = update_docker_image_tag_in_metadata_result.output steps_results.append(update_docker_image_tag_in_metadata_result) add_changelog_entry = AddChangelogEntry( @@ -176,7 +176,7 @@ async def run_connector_version_bump_pipeline( ) add_changelog_entry_result = await add_changelog_entry.run() steps_results.append(add_changelog_entry_result) - final_repo_dir = add_changelog_entry_result.output_artifact + final_repo_dir = add_changelog_entry_result.output await og_repo_dir.diff(final_repo_dir).export(str(git.get_git_repo_path())) report = ConnectorReport(context, steps_results, name="CONNECTOR VERSION BUMP RESULTS") context.report = report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_base_image/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_base_image/pipeline.py index 47fba701ff99..cb1f6d357d3a 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_base_image/pipeline.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_base_image/pipeline.py @@ -64,7 +64,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Could not find a base image for this connector language.", - output_artifact=self.repo_dir, + output=self.repo_dir, ) metadata_path = self.context.connector.metadata_file_path @@ -76,7 +76,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Connector does not have a base image metadata field.", - output_artifact=self.repo_dir, + output=self.repo_dir, ) if current_base_image_address == latest_base_image_address: @@ -84,7 +84,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Connector already uses latest base image", - output_artifact=self.repo_dir, + output=self.repo_dir, ) updated_metadata = self.update_base_image_in_metadata(current_metadata, latest_base_image_address) updated_repo_dir = metadata_change_helpers.get_repo_dir_with_updated_metadata(self.repo_dir, metadata_path, updated_metadata) @@ -93,7 +93,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SUCCESS, stdout=f"Updated base image to {latest_base_image_address} in {metadata_path}", - output_artifact=updated_repo_dir, + output=updated_repo_dir, ) @@ -146,7 +146,7 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.SKIPPED, stdout="Connector does not have a documentation file.", - output_artifact=self.repo_dir, + output=self.repo_dir, ) current_readme = await (await self.context.get_connector_dir(include=["README.md"])).file("README.md").contents() try: @@ -156,14 +156,14 @@ async def _run(self) -> StepResult: step=self, status=StepStatus.FAILURE, stdout=str(e), - output_artifact=self.repo_dir, + output=self.repo_dir, ) updated_repo_dir = await self.repo_dir.with_new_file(str(readme_path), contents=updated_readme) return StepResult( step=self, status=StepStatus.SUCCESS, stdout=f"Added build instructions to {readme_path}", - output_artifact=updated_repo_dir, + output=updated_repo_dir, ) def add_build_instructions(self, og_doc_content: str) -> str: @@ -276,7 +276,7 @@ async def run_connector_base_image_upgrade_pipeline(context: ConnectorContext, s ) update_base_image_in_metadata_result = await update_base_image_in_metadata.run() steps_results.append(update_base_image_in_metadata_result) - final_repo_dir = update_base_image_in_metadata_result.output_artifact + final_repo_dir = update_base_image_in_metadata_result.output await og_repo_dir.diff(final_repo_dir).export(str(git.get_git_repo_path())) report = ConnectorReport(context, steps_results, name="BASE IMAGE UPGRADE RESULTS") context.report = report @@ -324,7 +324,7 @@ async def run_connector_migration_to_base_image_pipeline( new_version = get_bumped_version(context.connector.version, "patch") bump_version_in_metadata = BumpDockerImageTagInMetadata( context, - update_base_image_in_metadata_result.output_artifact, + update_base_image_in_metadata_result.output, new_version, ) bump_version_in_metadata_result = await bump_version_in_metadata.run() @@ -333,7 +333,7 @@ async def run_connector_migration_to_base_image_pipeline( # ADD CHANGELOG ENTRY add_changelog_entry = AddChangelogEntry( context, - bump_version_in_metadata_result.output_artifact, + bump_version_in_metadata_result.output, new_version, "Base image migration: remove Dockerfile and use the python-connector-base image", pull_request_number, @@ -344,13 +344,13 @@ async def run_connector_migration_to_base_image_pipeline( # UPDATE DOC add_build_instructions_to_doc = AddBuildInstructionsToReadme( context, - add_changelog_entry_result.output_artifact, + add_changelog_entry_result.output, ) add_build_instructions_to_doc_results = await add_build_instructions_to_doc.run() steps_results.append(add_build_instructions_to_doc_results) # EXPORT MODIFIED FILES BACK TO HOST - final_repo_dir = add_build_instructions_to_doc_results.output_artifact + final_repo_dir = add_build_instructions_to_doc_results.output await og_repo_dir.diff(final_repo_dir).export(str(git.get_git_repo_path())) report = ConnectorReport(context, steps_results, name="MIGRATE TO BASE IMAGE RESULTS") context.report = report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py index 849a9348f115..88c917211946 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py @@ -313,7 +313,7 @@ def create_connector_report(results: List[StepResult]) -> ConnectorReport: if build_connector_results.status is not StepStatus.SUCCESS: return create_connector_report(results) - built_connector_platform_variants = list(build_connector_results.output_artifact.values()) + built_connector_platform_variants = list(build_connector_results.output.values()) push_connector_image_results = await PushConnectorImageToRegistry(context).run(built_connector_platform_variants) results.append(push_connector_image_results) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py index b8265c4385a1..594b9573ee57 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py @@ -6,13 +6,15 @@ import json import webbrowser from dataclasses import dataclass -from typing import TYPE_CHECKING +from pathlib import Path +from types import MappingProxyType +from typing import TYPE_CHECKING, Dict -from anyio import Path from connector_ops.utils import console # type: ignore from jinja2 import Environment, PackageLoader, select_autoescape from pipelines.consts import GCS_PUBLIC_DOMAIN from pipelines.helpers.utils import format_duration +from pipelines.models.artifacts import Artifact from pipelines.models.reports import Report from pipelines.models.steps import StepStatus from rich.console import Group @@ -42,13 +44,19 @@ def report_output_prefix(self) -> str: def html_report_file_name(self) -> str: return self.filename + ".html" + def file_remote_storage_key(self, file_name: str) -> str: + return f"{self.report_output_prefix}/{file_name}" + @property def html_report_remote_storage_key(self) -> str: - return f"{self.report_output_prefix}/{self.html_report_file_name}" + return self.file_remote_storage_key(self.html_report_file_name) + + def file_url(self, file_name: str) -> str: + return f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{self.file_remote_storage_key(file_name)}" @property def html_report_url(self) -> str: - return f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{self.html_report_remote_storage_key}" + return self.file_url(self.html_report_file_name) def to_json(self) -> str: """Create a JSON representation of the connector test report. @@ -81,7 +89,7 @@ def to_json(self) -> str: } ) - async def to_html(self) -> str: + def to_html(self) -> str: env = Environment( loader=PackageLoader("pipelines.airbyte_ci.connectors.test.steps"), autoescape=select_autoescape(), @@ -91,7 +99,18 @@ async def to_html(self) -> str: template = env.get_template("test_report.html.j2") template.globals["StepStatus"] = StepStatus template.globals["format_duration"] = format_duration - local_icon_path = await Path(f"{self.pipeline_context.connector.code_directory}/icon.svg").resolve() + local_icon_path = Path(f"{self.pipeline_context.connector.code_directory}/icon.svg").resolve() + step_result_to_artifact_links: Dict[str, List[Dict]] = {} + for step_result in self.steps_results: + for artifact in step_result.artifacts: + if artifact.gcs_url: + url = artifact.gcs_url + elif artifact.local_path: + url = artifact.local_path.resolve().as_uri() + else: + continue + step_result_to_artifact_links.setdefault(step_result.step.title, []).append({"name": artifact.name, "url": url}) + template_context = { "connector_name": self.pipeline_context.connector.technical_name, "step_results": self.steps_results, @@ -104,6 +123,8 @@ async def to_html(self) -> str: "git_revision": self.pipeline_context.git_revision, "commit_url": None, "icon_url": local_icon_path.as_uri(), + "report": self, + "step_result_to_artifact_links": MappingProxyType(step_result_to_artifact_links), } if self.pipeline_context.is_ci: @@ -116,18 +137,32 @@ async def to_html(self) -> str: ] = f"https://raw.githubusercontent.com/airbytehq/airbyte/{self.pipeline_context.git_revision}/{self.pipeline_context.connector.code_directory}/icon.svg" return template.render(template_context) + async def save_html_report(self) -> None: + """Save the report as HTML, upload it to GCS if the pipeline is running in CI""" + + html_report_path = self.report_dir_path / self.html_report_file_name + report_dir = self.pipeline_context.dagger_client.host().directory(str(self.report_dir_path)) + local_html_report_file = report_dir.with_new_file(self.html_report_file_name, self.to_html()).file(self.html_report_file_name) + html_report_artifact = Artifact(name="HTML Report", content_type="text/html", content=local_html_report_file) + await html_report_artifact.save_to_local_path(html_report_path) + absolute_path = html_report_path.absolute() + self.pipeline_context.logger.info(f"Report saved locally at {absolute_path}") + if self.remote_storage_enabled and self.pipeline_context.ci_gcs_credentials_secret and self.pipeline_context.ci_report_bucket: + gcs_url = await html_report_artifact.upload_to_gcs( + dagger_client=self.pipeline_context.dagger_client, + bucket=self.pipeline_context.ci_report_bucket, + key=self.html_report_remote_storage_key, + gcs_credentials=self.pipeline_context.ci_gcs_credentials_secret, + ) + self.pipeline_context.logger.info(f"HTML report uploaded to {gcs_url}") + + elif self.pipeline_context.enable_report_auto_open: + self.pipeline_context.logger.info("Opening HTML report in browser.") + webbrowser.open(absolute_path.as_uri()) + async def save(self) -> None: - local_html_path = await self.save_local(self.html_report_file_name, await self.to_html()) - absolute_path = await local_html_path.resolve() - if self.pipeline_context.enable_report_auto_open: - self.pipeline_context.logger.info(f"HTML report saved locally: {absolute_path}") - if self.pipeline_context.enable_report_auto_open: - self.pipeline_context.logger.info("Opening HTML report in browser.") - webbrowser.open(absolute_path.as_uri()) - if self.remote_storage_enabled: - await self.save_remote(local_html_path, self.html_report_remote_storage_key, "text/html") - self.pipeline_context.logger.info(f"HTML report uploaded to {self.html_report_url}") await super().save() + await self.save_html_report() def print(self) -> None: """Print the test report to the console in a nice way.""" diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py index c69a0ac4fb42..a4259b8f67c8 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py @@ -38,7 +38,7 @@ class IntegrationTests(GradleTask): gradle_task_name = "integrationTestJava" mount_connector_secrets = True bind_to_docker_host = True - with_test_report = True + with_test_artifacts = True @property def default_params(self) -> STEP_PARAMS: @@ -80,7 +80,7 @@ class UnitTests(GradleTask): title = "Java Connector Unit Tests" gradle_task_name = "test" bind_to_docker_host = True - with_test_report = True + with_test_artifacts = True def _create_integration_step_args_factory(context: ConnectorContext) -> Callable: @@ -90,14 +90,14 @@ def _create_integration_step_args_factory(context: ConnectorContext) -> Callable async def _create_integration_step_args(results: RESULTS_DICT) -> Dict[str, Optional[File]]: - connector_container = results["build"].output_artifact[LOCAL_BUILD_PLATFORM] + connector_container = results["build"].output[LOCAL_BUILD_PLATFORM] connector_image_tar_file, _ = await export_container_to_tarball(context, connector_container, LOCAL_BUILD_PLATFORM) if context.connector.supports_normalization: tar_file_name = f"{context.connector.normalization_repository}_{context.git_revision}.tar" build_normalization_results = results["build_normalization"] - normalization_container = build_normalization_results.output_artifact + normalization_container = build_normalization_results.output normalization_tar_file, _ = await export_container_to_tarball( context, normalization_container, LOCAL_BUILD_PLATFORM, tar_file_name=tar_file_name ) @@ -138,9 +138,7 @@ def _get_acceptance_test_steps(context: ConnectorContext) -> List[StepToRun]: StepToRun( id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, step=AcceptanceTests(context, True), - args=lambda results: { - "connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM] - }, + args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], ), ] @@ -159,7 +157,7 @@ def get_test_steps(context: ConnectorContext) -> STEP_TREE: id=CONNECTOR_TEST_STEP_ID.BUILD, step=BuildConnectorImages(context), args=lambda results: { - "dist_dir": results[CONNECTOR_TEST_STEP_ID.BUILD_TAR].output_artifact.directory(dist_tar_directory_path(context)) + "dist_dir": results[CONNECTOR_TEST_STEP_ID.BUILD_TAR].output.directory(dist_tar_directory_path(context)) }, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD_TAR], ), diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py index c19c807fcea0..c7cc04cea7f3 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py @@ -253,7 +253,7 @@ def get_test_steps(context: ConnectorContext) -> STEP_TREE: StepToRun( id=CONNECTOR_TEST_STEP_ID.UNIT, step=UnitTests(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM]}, + args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], ) ], @@ -261,21 +261,19 @@ def get_test_steps(context: ConnectorContext) -> STEP_TREE: StepToRun( id=CONNECTOR_TEST_STEP_ID.INTEGRATION, step=IntegrationTests(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM]}, + args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], ), StepToRun( id=CONNECTOR_TEST_STEP_ID.AIRBYTE_LIB_VALIDATION, step=AirbyteLibValidation(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM]}, + args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], ), StepToRun( id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, step=AcceptanceTests(context, context.concurrent_cat), - args=lambda results: { - "connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM] - }, + args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], ), ], diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 index 7835305a7535..d0027605d0bf 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 @@ -82,7 +82,7 @@ transition: max-height .25s ease-in-out; } .toggle:checked + .lbl-toggle + .collapsible-content { - max-height: 100vh; + max-height: 70vh; } .toggle:checked + .lbl-toggle { border-bottom-right-radius: 0; @@ -110,6 +110,14 @@ } +

{{ connector_name }} test report

    @@ -159,19 +167,23 @@ {% endif %}
    + {% if step_result_to_artifact_links[step_result.step.title] %} +

    Artifacts

    +
      + {% for artifact in step_result_to_artifact_links[step_result.step.title] %} +
    • {{ artifact.name }}
    • + {% endfor %} +
    + {% endif %}
    {% if step_result.stdout %} - Standard output: + Standard output():
    {{ step_result.stdout }}
    {% endif %} {% if step_result.stderr %} - Standard error: + Standard error():
    {{ step_result.stderr }}
    {% endif %} - {% if step_result.report %} - Report: -
    {{ step_result.report }}
    - {% endif %}
diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py index 6824f9d25550..8af4baab6a75 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py @@ -59,9 +59,7 @@ async def _run(self) -> StepResult: status=StepStatus.FAILURE, stdout="Could not export diff to local git repo.", ) - return StepResult( - step=self, status=StepStatus.SUCCESS, stdout=f"Updated CDK version to {self.new_version}", output_artifact=diff - ) + return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"Updated CDK version to {self.new_version}", output=diff) except ValueError as e: return StepResult( step=self, diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/format_command.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/format_command.py index aeb17b08e504..5787c2c67132 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/format_command.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/format_command.py @@ -124,7 +124,7 @@ async def invoke(self, ctx: click.Context, click_pipeline_context: ClickPipeline container = self.get_format_container_fn(dagger_client, dir_to_format) command_result = await self.get_format_command_result(dagger_client, container, dir_to_format) - if (formatted_code_dir := command_result.output_artifact) and self.export_formatted_code: + if (formatted_code_dir := command_result.output) and self.export_formatted_code: await formatted_code_dir.export(self.LOCAL_REPO_PATH) if self._enable_logging: @@ -203,9 +203,7 @@ async def get_format_command_result( if await dir_with_modified_files.entries(): modified_files = await list_files_in_directory(dagger_client, dir_with_modified_files) self.logger.debug(f"Modified files: {modified_files}") - return CommandResult( - command=self, status=StepStatus.FAILURE, stdout=stdout, stderr=stderr, output_artifact=dir_with_modified_files - ) + return CommandResult(command=self, status=StepStatus.FAILURE, stdout=stdout, stderr=stderr, output=dir_with_modified_files) return CommandResult(command=self, status=StepStatus.SUCCESS, stdout=stdout, stderr=stderr) except dagger.ExecError as e: return CommandResult(command=self, status=StepStatus.FAILURE, stderr=e.stderr, stdout=e.stdout, exc_info=e) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py index 0fd139e20c33..456e6c3f1aa3 100644 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py +++ b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py @@ -1,19 +1,18 @@ # # Copyright (c) 2023 Airbyte, Inc., all rights reserved. # -import html -import re from abc import ABC -from typing import Any, ClassVar, List, Optional, Tuple +from datetime import datetime +from typing import Any, ClassVar, List, Optional, Tuple, cast import pipelines.dagger.actions.system.docker -import xmltodict -from dagger import CacheSharingMode, CacheVolume, Container, QueryError +from dagger import CacheSharingMode, CacheVolume, Container, ExecError from pipelines.airbyte_ci.connectors.context import ConnectorContext from pipelines.consts import AMAZONCORRETTO_IMAGE from pipelines.dagger.actions import secrets from pipelines.hacks import never_fail_exec -from pipelines.helpers.utils import sh_dash_c +from pipelines.helpers.utils import dagger_directory_as_zip_file, sh_dash_c +from pipelines.models.artifacts import Artifact from pipelines.models.steps import Step, StepResult @@ -36,7 +35,7 @@ class GradleTask(Step, ABC): gradle_task_name: ClassVar[str] bind_to_docker_host: ClassVar[bool] = False mount_connector_secrets: ClassVar[bool] = False - with_test_report: ClassVar[bool] = False + with_test_artifacts: ClassVar[bool] = False accept_extra_params = True @property @@ -193,9 +192,18 @@ async def _run(self, *args: Any, **kwargs: Any) -> StepResult: connector_gradle_task = f":airbyte-integrations:connectors:{self.context.connector.technical_name}:{self.gradle_task_name}" gradle_command = self._get_gradle_command(connector_gradle_task, task_options=self.params_as_cli_options) gradle_container = gradle_container.with_(never_fail_exec([gradle_command])) - return await self.get_step_result(gradle_container) - async def get_step_result(self, container: Container) -> StepResult: + # Collect the test artifacts, if applicable. + artifacts = [] + if self.with_test_artifacts: + if test_logs := await self._collect_test_logs(gradle_container): + artifacts.append(test_logs) + if test_results := await self._collect_test_results(gradle_container): + artifacts.append(test_results) + + return await self.get_step_result(gradle_container, artifacts) + + async def get_step_result(self, container: Container, outputs: List[Artifact]) -> StepResult: step_result = await super().get_step_result(container) # Decorate with test report, if applicable. return StepResult( @@ -203,76 +211,75 @@ async def get_step_result(self, container: Container) -> StepResult: status=step_result.status, stdout=step_result.stdout, stderr=step_result.stderr, - report=await self._collect_test_report(container), - output_artifact=step_result.output_artifact, + output=step_result.output, + artifacts=outputs, ) - async def _collect_test_report(self, gradle_container: Container) -> Optional[str]: - if not self.with_test_report: + async def _collect_test_logs(self, gradle_container: Container) -> Optional[Artifact]: + """ + Exports the java docs from the container into the host filesystem. + The docs in the container are expected to be in build/test-logs, and will end up test-artifact directory by default + One can change the destination directory by setting the outputs + """ + test_logs_dir_name_in_container = "test-logs" + test_logs_dir_name_in_zip = f"test-logs-{datetime.fromtimestamp(cast(float, self.context.pipeline_start_timestamp)).isoformat()}-{self.context.git_branch}-{self.gradle_task_name}".replace( + "/", "_" + ) + if ( + test_logs_dir_name_in_container + not in await gradle_container.directory(f"{self.context.connector.code_directory}/build").entries() + ): + self.context.logger.warn(f"No {test_logs_dir_name_in_container} found directory in the build folder") return None + try: + zip_file = await ( + dagger_directory_as_zip_file( + self.dagger_client, + await gradle_container.directory(f"{self.context.connector.code_directory}/build/{test_logs_dir_name_in_container}"), + test_logs_dir_name_in_zip, + ) + ) + return Artifact( + name=f"{test_logs_dir_name_in_zip}.zip", + content=zip_file, + content_type="application/zip", + to_upload=True, + ) + except ExecError as e: + self.context.logger.error(str(e)) + return None - junit_xml_path = f"{self.context.connector.code_directory}/build/test-results/{self.gradle_task_name}" - testsuites = [] + async def _collect_test_results(self, gradle_container: Container) -> Optional[Artifact]: + """ + Exports the junit test reports from the container into the host filesystem. + The docs in the container are expected to be in build/test-results, and will end up test-artifact directory by default + Only the XML files generated by junit are downloaded into the host filesystem + One can change the destination directory by setting the outputs + """ + test_results_dir_name_in_container = "test-results" + test_results_dir_name_in_zip = f"test-results-{datetime.fromtimestamp(cast(float, self.context.pipeline_start_timestamp)).isoformat()}-{self.context.git_branch}-{self.gradle_task_name}".replace( + "/", "_" + ) + if ( + test_results_dir_name_in_container + not in await gradle_container.directory(f"{self.context.connector.code_directory}/build").entries() + ): + self.context.logger.warn(f"No {test_results_dir_name_in_container} found directory in the build folder") + return None try: - junit_xml_dir = await gradle_container.directory(junit_xml_path) - for file_name in await junit_xml_dir.entries(): - if file_name.endswith(".xml"): - junit_xml = await junit_xml_dir.file(file_name).contents() - # This will be embedded in the HTML report in a
 block.
-                    # The java logging backend will have already taken care of masking any secrets.
-                    # Nothing to do in that regard.
-                    try:
-                        if testsuite := xmltodict.parse(junit_xml):
-                            testsuites.append(testsuite)
-                    except Exception as e:
-                        self.context.logger.error(str(e))
-                        self.context.logger.warn(f"Failed to parse junit xml file {file_name}.")
-        except QueryError as e:
+            zip_file = await (
+                dagger_directory_as_zip_file(
+                    self.dagger_client,
+                    await gradle_container.directory(f"{self.context.connector.code_directory}/build/{test_results_dir_name_in_container}"),
+                    test_results_dir_name_in_zip,
+                )
+            )
+            return Artifact(
+                name=f"{test_results_dir_name_in_zip}.zip",
+                content=zip_file,
+                content_type="application/zip",
+                to_upload=True,
+            )
+        except ExecError as e:
             self.context.logger.error(str(e))
-            self.context.logger.warn(f"Failed to retrieve junit test results from {junit_xml_path} gradle container.")
             return None
-        return render_junit_xml(testsuites)
-
-
-MAYBE_STARTS_WITH_XML_TAG = re.compile("^ *<")
-ESCAPED_ANSI_COLOR_PATTERN = re.compile(r"\?\[0?m|\?\[[34][0-9]m")
-
-
-def render_junit_xml(testsuites: List[Any]) -> str:
-    """Renders the JUnit XML report as something readable in the HTML test report."""
-    # Transform the dict contents.
-    indent = "  "
-    for testsuite in testsuites:
-        testsuite = testsuite.get("testsuite")
-        massage_system_out_and_err(testsuite, indent, 4)
-        if testcases := testsuite.get("testcase"):
-            if not isinstance(testcases, list):
-                testcases = [testcases]
-            for testcase in testcases:
-                massage_system_out_and_err(testcase, indent, 5)
-    # Transform back to XML string.
-    # Try to respect the JUnit XML test result schema.
-    root = {"testsuites": {"testsuite": testsuites}}
-    xml = xmltodict.unparse(root, pretty=True, short_empty_elements=True, indent=indent)
-    # Escape < and > and so forth to make them render properly, but not in the log messages.
-    # These lines will already have been escaped by xmltodict.unparse.
-    lines = xml.splitlines()
-    for idx, line in enumerate(lines):
-        if MAYBE_STARTS_WITH_XML_TAG.match(line):
-            lines[idx] = html.escape(line)
-    return "\n".join(lines)
-
-
-def massage_system_out_and_err(d: dict, indent: str, indent_levels: int) -> None:
-    """Makes the system-out and system-err text prettier."""
-    if d:
-        for key in ["system-out", "system-err"]:
-            if s := d.get(key):
-                lines = s.splitlines()
-                s = ""
-                for line in lines:
-                    stripped = line.strip()
-                    if stripped:
-                        s += "\n" + indent * indent_levels + ESCAPED_ANSI_COLOR_PATTERN.sub("", line.strip())
-                s = s + "\n" + indent * (indent_levels - 1) if s else None
-                d[key] = s
diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py
index e275b42610bf..cd8d31dd4d40 100644
--- a/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py
+++ b/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py
@@ -19,7 +19,7 @@
 import anyio
 import asyncclick as click
 import asyncer
-from dagger import Client, Config, Container, ExecError, File, ImageLayerCompression, Platform, Secret
+from dagger import Client, Config, Container, Directory, ExecError, File, ImageLayerCompression, Platform, Secret
 from more_itertools import chunked
 
 if TYPE_CHECKING:
@@ -353,3 +353,24 @@ def java_log_scrub_pattern(secrets_to_mask: List[str]) -> str:
             ":": ":",
         },
     )
+
+
+def dagger_directory_as_zip_file(dagger_client: Client, directory: Directory, directory_name: str) -> File:
+    """Compress a directory and return a File object representing the zip file.
+
+    Args:
+        dagger_client (Client): The dagger client.
+        directory (Path): The directory to compress.
+        directory_name (str): The name of the directory.
+
+    Returns:
+        File: The File object representing the zip file.
+    """
+    return (
+        dagger_client.container()
+        .from_("alpine:3.19.1")
+        .with_exec(sh_dash_c(["apk update", "apk add zip"]))
+        .with_mounted_directory(f"/{directory_name}", directory)
+        .with_exec(["zip", "-r", "/zipped.zip", f"/{directory_name}"])
+        .file("/zipped.zip")
+    )
diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py b/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py
new file mode 100644
index 000000000000..f1deafd445e7
--- /dev/null
+++ b/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
+
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Optional
+
+import dagger
+from pipelines.consts import GCS_PUBLIC_DOMAIN
+from pipelines.dagger.actions import remote_storage
+
+
+@dataclass(kw_only=True)
+class Artifact:
+    """A dataclass to represent an artifact produced by a pipeline execution."""
+
+    name: str
+    content_type: str
+    content: dagger.File
+    to_upload: bool = True
+    local_path: Optional[Path] = None
+    gcs_url: Optional[str] = None
+
+    async def save_to_local_path(self, path: Path) -> Path:
+        exported = await self.content.export(str(path))
+        if exported:
+            self.local_path = path
+            return path
+        else:
+            raise Exception(f"Failed to save artifact {self.name} to local path {path}")
+
+    async def upload_to_gcs(self, dagger_client: dagger.Client, bucket: str, key: str, gcs_credentials: dagger.Secret) -> str:
+        gcs_cp_flags = [f'--content-disposition=filename="{self.name}"']
+        if self.content_type is not None:
+            gcs_cp_flags = gcs_cp_flags + [f"--content-type={self.content_type}"]
+
+        report_upload_exit_code, _, _ = await remote_storage.upload_to_gcs(
+            dagger_client=dagger_client,
+            file_to_upload=self.content,
+            key=key,
+            bucket=bucket,
+            gcs_credentials=gcs_credentials,
+            flags=gcs_cp_flags,
+        )
+        if report_upload_exit_code != 0:
+            raise Exception(f"Failed to upload artifact {self.name} to GCS. Exit code: {report_upload_exit_code}.")
+        self.gcs_url = f"{GCS_PUBLIC_DOMAIN}/{bucket}/{key}"
+        return f"{GCS_PUBLIC_DOMAIN}/{bucket}/{key}"
diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/reports.py b/airbyte-ci/connectors/pipelines/pipelines/models/reports.py
index 206e1c44e9e1..4cf5c33f8055 100644
--- a/airbyte-ci/connectors/pipelines/pipelines/models/reports.py
+++ b/airbyte-ci/connectors/pipelines/pipelines/models/reports.py
@@ -7,17 +7,17 @@
 from __future__ import annotations
 
 import json
+import time
 import typing
 from dataclasses import dataclass, field
 from datetime import datetime, timedelta
+from pathlib import Path
 from typing import List
 
-import anyio
-from anyio import Path
 from connector_ops.utils import console  # type: ignore
-from pipelines.consts import GCS_PUBLIC_DOMAIN, LOCAL_REPORTS_PATH_ROOT
-from pipelines.dagger.actions import remote_storage
-from pipelines.helpers.utils import format_duration
+from pipelines.consts import LOCAL_REPORTS_PATH_ROOT
+from pipelines.helpers.utils import format_duration, slugify
+from pipelines.models.artifacts import Artifact
 from pipelines.models.steps import StepResult, StepStatus
 from rich.console import Group
 from rich.panel import Panel
@@ -44,6 +44,10 @@ class Report:
     def report_output_prefix(self) -> str:
         return self.pipeline_context.report_output_prefix
 
+    @property
+    def report_dir_path(self) -> Path:
+        return Path(f"{LOCAL_REPORTS_PATH_ROOT}/{self.report_output_prefix}")
+
     @property
     def json_report_file_name(self) -> str:
         return self.filename + ".json"
@@ -84,42 +88,52 @@ def lead_duration(self) -> timedelta:
     def remote_storage_enabled(self) -> bool:
         return self.pipeline_context.is_ci
 
-    async def save_local(self, filename: str, content: str) -> Path:
-        """Save the report files locally."""
-        local_path = anyio.Path(f"{LOCAL_REPORTS_PATH_ROOT}/{self.report_output_prefix}/{filename}")
-        await local_path.parents[0].mkdir(parents=True, exist_ok=True)
-        await local_path.write_text(content)
-        return local_path
-
-    async def save_remote(self, local_path: Path, remote_key: str, content_type: str) -> int:
-        assert self.pipeline_context.ci_report_bucket is not None, "The ci_report_bucket must be set to save reports."
-
-        gcs_cp_flags = None if content_type is None else [f"--content-type={content_type}"]
-        local_file = self.pipeline_context.dagger_client.host().directory(".", include=[str(local_path)]).file(str(local_path))
-        report_upload_exit_code, _, _ = await remote_storage.upload_to_gcs(
-            dagger_client=self.pipeline_context.dagger_client,
-            file_to_upload=local_file,
-            key=remote_key,
-            bucket=self.pipeline_context.ci_report_bucket,
-            gcs_credentials=self.pipeline_context.ci_gcs_credentials_secret,
-            flags=gcs_cp_flags,
-        )
-        gcs_uri = "gs://" + self.pipeline_context.ci_report_bucket + "/" + remote_key
-        public_url = f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{remote_key}"
-        if report_upload_exit_code != 0:
-            self.pipeline_context.logger.error(f"Uploading {local_path} to {gcs_uri} failed.")
-        else:
-            self.pipeline_context.logger.info(f"Uploading {local_path} to {gcs_uri} succeeded. Public URL: {public_url}")
-        return report_upload_exit_code
-
     async def save(self) -> None:
-        """Save the report files."""
-
-        local_json_path = await self.save_local(self.json_report_file_name, self.to_json())
-        absolute_path = await local_json_path.absolute()
+        self.report_dir_path.mkdir(parents=True, exist_ok=True)
+        await self.save_json_report()
+        await self.save_step_result_artifacts()
+
+    async def save_json_report(self) -> None:
+        """Save the report as JSON, upload it to GCS if the pipeline is running in CI"""
+
+        json_report_path = self.report_dir_path / self.json_report_file_name
+        report_dir = self.pipeline_context.dagger_client.host().directory(str(self.report_dir_path))
+        local_json_report_file = report_dir.with_new_file(self.json_report_file_name, self.to_json()).file(self.json_report_file_name)
+        json_report_artifact = Artifact(name="JSON Report", content_type="application/json", content=local_json_report_file)
+        await json_report_artifact.save_to_local_path(json_report_path)
+        absolute_path = json_report_path.absolute()
         self.pipeline_context.logger.info(f"Report saved locally at {absolute_path}")
-        if self.remote_storage_enabled:
-            await self.save_remote(local_json_path, self.json_report_remote_storage_key, "application/json")
+        if self.remote_storage_enabled and self.pipeline_context.ci_report_bucket and self.pipeline_context.ci_gcs_credentials_secret:
+            gcs_url = await json_report_artifact.upload_to_gcs(
+                dagger_client=self.pipeline_context.dagger_client,
+                bucket=self.pipeline_context.ci_report_bucket,
+                key=self.json_report_remote_storage_key,
+                gcs_credentials=self.pipeline_context.ci_gcs_credentials_secret,
+            )
+            self.pipeline_context.logger.info(f"JSON Report uploaded to {gcs_url}")
+
+    async def save_step_result_artifacts(self) -> None:
+        local_artifacts_dir = self.report_dir_path / "artifacts"
+        local_artifacts_dir.mkdir(parents=True, exist_ok=True)
+        # TODO: concurrent save and upload
+        for step_result in self.steps_results:
+            for artifact in step_result.artifacts:
+                step_artifacts_dir = local_artifacts_dir / slugify(step_result.step.title)
+                step_artifacts_dir.mkdir(parents=True, exist_ok=True)
+                await artifact.save_to_local_path(step_artifacts_dir / artifact.name)
+                if (
+                    self.remote_storage_enabled
+                    and self.pipeline_context.ci_report_bucket
+                    and self.pipeline_context.ci_gcs_credentials_secret
+                ):
+                    upload_time = int(time.time())
+                    gcs_url = await artifact.upload_to_gcs(
+                        dagger_client=self.pipeline_context.dagger_client,
+                        bucket=self.pipeline_context.ci_report_bucket,
+                        key=f"{self.report_output_prefix}/artifacts/{slugify(step_result.step.title)}/{upload_time}_{artifact.name}",
+                        gcs_credentials=self.pipeline_context.ci_gcs_credentials_secret,
+                    )
+                    self.pipeline_context.logger.info(f"Artifact {artifact.name} for {step_result.step.title} uploaded to {gcs_url}")
 
     def to_json(self) -> str:
         """Create a JSON representation of the report.
diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/steps.py b/airbyte-ci/connectors/pipelines/pipelines/models/steps.py
index edc97079a32f..86be5550f713 100644
--- a/airbyte-ci/connectors/pipelines/pipelines/models/steps.py
+++ b/airbyte-ci/connectors/pipelines/pipelines/models/steps.py
@@ -19,6 +19,7 @@
 from pipelines import main_logger
 from pipelines.helpers import sentry_utils
 from pipelines.helpers.utils import format_duration, get_exec_result
+from pipelines.models.artifacts import Artifact
 
 if TYPE_CHECKING:
     from typing import Any, ClassVar, Optional, Union
@@ -73,7 +74,8 @@ class Result:
     stdout: Optional[str] = None
     report: Optional[str] = None
     exc_info: Optional[Exception] = None
-    output_artifact: Any = None
+    output: Any = None
+    artifacts: List[Artifact] = field(default_factory=list)
 
     @property
     def success(self) -> bool:
@@ -387,7 +389,7 @@ def get_step_status_from_exit_code(
         else:
             return StepStatus.FAILURE
 
-    async def get_step_result(self, container: Container) -> StepResult:
+    async def get_step_result(self, container: Container, *args: Any, **kwargs: Any) -> StepResult:
         """Concurrent retrieval of exit code, stdout and stdout of a container.
 
         Create a StepResult object from these objects.
@@ -404,7 +406,7 @@ async def get_step_result(self, container: Container) -> StepResult:
             status=self.get_step_status_from_exit_code(exit_code),
             stderr=stderr,
             stdout=stdout,
-            output_artifact=container,
+            output=container,
         )
 
     def _get_timed_out_step_result(self) -> StepResult:
diff --git a/airbyte-ci/connectors/pipelines/pyproject.toml b/airbyte-ci/connectors/pipelines/pyproject.toml
index d6cca9affdc0..cc7abba8285d 100644
--- a/airbyte-ci/connectors/pipelines/pyproject.toml
+++ b/airbyte-ci/connectors/pipelines/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
 name = "pipelines"
-version = "4.3.2"
+version = "4.4.0"
 description = "Packaged maintained by the connector operations team to perform CI for connectors' pipelines"
 authors = ["Airbyte "]
 
diff --git a/airbyte-ci/connectors/pipelines/tests/test_bases.py b/airbyte-ci/connectors/pipelines/tests/test_bases.py
index a109e1e33a0b..15808f2c88de 100644
--- a/airbyte-ci/connectors/pipelines/tests/test_bases.py
+++ b/airbyte-ci/connectors/pipelines/tests/test_bases.py
@@ -39,7 +39,7 @@ async def test_run_with_timeout(self, test_context):
         assert step_result.status == timed_out_step_result.status
         assert step_result.stdout == timed_out_step_result.stdout
         assert step_result.stderr == timed_out_step_result.stderr
-        assert step_result.output_artifact == timed_out_step_result.output_artifact
+        assert step_result.output == timed_out_step_result.output
         assert step.retry_count == step.max_retries + 1
 
     @pytest.mark.parametrize(
diff --git a/airbyte-ci/connectors/pipelines/tests/test_build_image/test_python_connectors.py b/airbyte-ci/connectors/pipelines/tests/test_build_image/test_python_connectors.py
index bb8ac23a10ea..084911d82cf1 100644
--- a/airbyte-ci/connectors/pipelines/tests/test_build_image/test_python_connectors.py
+++ b/airbyte-ci/connectors/pipelines/tests/test_build_image/test_python_connectors.py
@@ -117,14 +117,14 @@ async def test__run_using_base_image_with_mocks(self, mocker, test_context_with_
         container_built_from_base.with_exec.assert_called_with(["spec"])
         assert step_result.status is StepStatus.SUCCESS
         for platform in all_platforms:
-            assert step_result.output_artifact[platform] == container_built_from_base
+            assert step_result.output[platform] == container_built_from_base
 
     @pytest.mark.slow
     async def test_building_from_base_image_for_real(self, test_context_with_real_connector_using_base_image, current_platform):
         step = python_connectors.BuildConnectorImages(test_context_with_real_connector_using_base_image)
         step_result = await step._run()
         step_result.status is StepStatus.SUCCESS
-        built_container = step_result.output_artifact[current_platform]
+        built_container = step_result.output[current_platform]
         assert await built_container.env_variable("AIRBYTE_ENTRYPOINT") == " ".join(
             build_customization.get_entrypoint(step.context.connector)
         )
@@ -146,7 +146,7 @@ async def test_building_from_base_image_with_customization_for_real(
         step = python_connectors.BuildConnectorImages(test_context_with_real_connector_using_base_image_with_build_customization)
         step_result = await step._run()
         step_result.status is StepStatus.SUCCESS
-        built_container = step_result.output_artifact[current_platform]
+        built_container = step_result.output[current_platform]
         assert await built_container.env_variable("MY_PRE_BUILD_ENV_VAR") == "my_pre_build_env_var_value"
         assert await built_container.env_variable("MY_POST_BUILD_ENV_VAR") == "my_post_build_env_var_value"
 
@@ -161,7 +161,7 @@ async def test__run_using_base_dockerfile_with_mocks(self, mocker, test_context_
         container_built_from_dockerfile.with_exec.assert_called_with(["spec"])
         assert step_result.status is StepStatus.SUCCESS
         for platform in all_platforms:
-            assert step_result.output_artifact[platform] == container_built_from_dockerfile
+            assert step_result.output[platform] == container_built_from_dockerfile
 
     async def test_building_from_dockerfile_for_real(self, test_context_with_real_connector_without_base_image):
         step = python_connectors.BuildConnectorImages(test_context_with_real_connector_without_base_image)
diff --git a/airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_run_steps.py b/airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_run_steps.py
index 37bfa991eee0..2d0193676b1b 100644
--- a/airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_run_steps.py
+++ b/airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_run_steps.py
@@ -299,7 +299,7 @@ async def test_run_steps_passes_results():
         StepToRun(
             id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE,
             step=AcceptanceTests(context, True),
-            args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output_artifact[LOCAL_BUILD_PLATFORM]},
+            args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]},
             depends_on=[CONNECTOR_TEST_STEP_ID.BUILD],
         ),
 
@@ -309,23 +309,23 @@ class Simple(Step):
         title = "Test Step"
 
         async def _run(self, arg1, arg2) -> StepResult:
-            output_artifact = f"{arg1}:{arg2}"
-            return StepResult(step=self, status=StepStatus.SUCCESS, output_artifact=output_artifact)
+            output = f"{arg1}:{arg2}"
+            return StepResult(step=self, status=StepStatus.SUCCESS, output=output)
 
     async def async_args(results):
-        return {"arg1": results["step2"].output_artifact, "arg2": "4"}
+        return {"arg1": results["step2"].output, "arg2": "4"}
 
     steps = [
         [StepToRun(id="step1", step=Simple(test_context), args={"arg1": "1", "arg2": "2"})],
-        [StepToRun(id="step2", step=Simple(test_context), args=lambda results: {"arg1": results["step1"].output_artifact, "arg2": "3"})],
+        [StepToRun(id="step2", step=Simple(test_context), args=lambda results: {"arg1": results["step1"].output, "arg2": "3"})],
         [StepToRun(id="step3", step=Simple(test_context), args=async_args)],
     ]
 
     results = await run_steps(steps)
 
-    assert results["step1"].output_artifact == "1:2"
-    assert results["step2"].output_artifact == "1:2:3"
-    assert results["step3"].output_artifact == "1:2:3:4"
+    assert results["step1"].output == "1:2"
+    assert results["step2"].output == "1:2:3"
+    assert results["step3"].output == "1:2:3:4"
 
 
 @pytest.mark.anyio
diff --git a/airbyte-ci/connectors/pipelines/tests/test_publish.py b/airbyte-ci/connectors/pipelines/tests/test_publish.py
index 471c89ae6ece..f5cb73d0ca9e 100644
--- a/airbyte-ci/connectors/pipelines/tests/test_publish.py
+++ b/airbyte-ci/connectors/pipelines/tests/test_publish.py
@@ -278,12 +278,12 @@ async def test_run_connector_publish_pipeline_when_image_does_not_exist(
         name="check_connector_image_does_not_exist_result", status=StepStatus.SUCCESS
     )
 
-    # have output_artifact.values return []
+    # have output.values return []
     built_connector_platform = mocker.Mock()
     built_connector_platform.values.return_value = ["linux/amd64"]
 
     publish_pipeline.steps.run_connector_build.return_value = mocker.Mock(
-        name="build_connector_for_publish_result", status=build_step_status, output_artifact=built_connector_platform
+        name="build_connector_for_publish_result", status=build_step_status, output=built_connector_platform
     )
 
     publish_pipeline.PushConnectorImageToRegistry.return_value.run.return_value = mocker.Mock(
diff --git a/airbyte-ci/connectors/pipelines/tests/test_tests/test_python_connectors.py b/airbyte-ci/connectors/pipelines/tests/test_tests/test_python_connectors.py
index f6b718be42f3..f53b43ebe57a 100644
--- a/airbyte-ci/connectors/pipelines/tests/test_tests/test_python_connectors.py
+++ b/airbyte-ci/connectors/pipelines/tests/test_tests/test_python_connectors.py
@@ -48,7 +48,7 @@ def context_for_certified_connector_with_setup(self, mocker, certified_connector
     @pytest.fixture
     async def certified_container_with_setup(self, context_for_certified_connector_with_setup, current_platform):
         result = await BuildConnectorImages(context_for_certified_connector_with_setup).run()
-        return result.output_artifact[current_platform]
+        return result.output[current_platform]
 
     @pytest.fixture
     def context_for_connector_with_poetry(self, mocker, connector_with_poetry, dagger_client, current_platform):
@@ -69,7 +69,7 @@ def context_for_connector_with_poetry(self, mocker, connector_with_poetry, dagge
     @pytest.fixture
     async def container_with_poetry(self, context_for_connector_with_poetry, current_platform):
         result = await BuildConnectorImages(context_for_connector_with_poetry).run()
-        return result.output_artifact[current_platform]
+        return result.output[current_platform]
 
     async def test__run_for_setup_py(self, context_for_certified_connector_with_setup, certified_container_with_setup):
         # Assume that the tests directory is available
@@ -80,7 +80,7 @@ async def test__run_for_setup_py(self, context_for_certified_connector_with_setu
             "Total coverage:" in result.stdout
         ), "The pytest-cov package should be installed in the test environment and test coverage report should be displayed."
         assert "Required test coverage of" in result.stdout, "A test coverage threshold should be defined for certified connectors."
-        pip_freeze_output = await result.output_artifact.with_exec(["pip", "freeze"], skip_entrypoint=True).stdout()
+        pip_freeze_output = await result.output.with_exec(["pip", "freeze"], skip_entrypoint=True).stdout()
         assert (
             context_for_certified_connector_with_setup.connector.technical_name in pip_freeze_output
         ), "The connector should be installed in the test environment."
@@ -93,7 +93,7 @@ async def test__run_for_poetry(self, context_for_connector_with_poetry, containe
         assert isinstance(result, StepResult)
         # We only check for the presence of "test session starts" because we have no guarantee that the tests will pass
         assert "test session starts" in result.stdout or "test session starts" in result.stderr, "The pytest tests should have started."
-        pip_freeze_output = await result.output_artifact.with_exec(["poetry", "run", "pip", "freeze"], skip_entrypoint=True).stdout()
+        pip_freeze_output = await result.output.with_exec(["poetry", "run", "pip", "freeze"], skip_entrypoint=True).stdout()
 
         assert (
             context_for_connector_with_poetry.connector.technical_name in pip_freeze_output

From 64b54c10c5c327e3a4733206989f98d4b13451e9 Mon Sep 17 00:00:00 2001
From: Artem Inzhyyants <36314070+artem1205@users.noreply.github.com>
Date: Thu, 22 Feb 2024 18:06:27 +0100
Subject: [PATCH 23/74] Source SalesForce: Add Stream Slice Step option to
 specification (#35421)

Signed-off-by: Artem Inzhyyants 
---
 .../acceptance-test-config.yml                |  2 +
 .../integration_tests/expected_records.jsonl  |  6 +-
 .../source-salesforce/metadata.yaml           |  4 +-
 .../connectors/source-salesforce/poetry.lock  | 10 +--
 .../source-salesforce/pyproject.toml          |  4 +-
 .../source_salesforce/source.py               | 22 ++++-
 .../source_salesforce/spec.yaml               | 14 ++-
 .../source_salesforce/streams.py              | 33 ++++---
 .../source-salesforce/unit_tests/api_test.py  | 90 ++++++++++++-------
 .../source-salesforce/unit_tests/conftest.py  | 13 ++-
 docs/integrations/sources/salesforce.md       |  5 +-
 11 files changed, 140 insertions(+), 63 deletions(-)

diff --git a/airbyte-integrations/connectors/source-salesforce/acceptance-test-config.yml b/airbyte-integrations/connectors/source-salesforce/acceptance-test-config.yml
index c3c2133f001c..a78ff7a81fc8 100644
--- a/airbyte-integrations/connectors/source-salesforce/acceptance-test-config.yml
+++ b/airbyte-integrations/connectors/source-salesforce/acceptance-test-config.yml
@@ -48,6 +48,8 @@ acceptance_tests:
         future_state:
           future_state_path: "integration_tests/future_state.json"
         timeout_seconds: 7200
+        # skip incremental tests as filter condition greater than or equal is used, so last record for any stream state is duplicated
+        skip_comprehensive_incremental_tests: true
   full_refresh:
     tests:
       - config_path: "secrets/config.json"
diff --git a/airbyte-integrations/connectors/source-salesforce/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-salesforce/integration_tests/expected_records.jsonl
index 14552380db0e..e556cda7b5a1 100644
--- a/airbyte-integrations/connectors/source-salesforce/integration_tests/expected_records.jsonl
+++ b/airbyte-integrations/connectors/source-salesforce/integration_tests/expected_records.jsonl
@@ -10,9 +10,9 @@
 {"stream": "ActiveProfileMetric", "data": {"Id": "5H04W00000U3Ph4SAF", "MetricsDate": "2023-10-22", "UserLicenseId": "1004W000001gXv2QAE", "ProfileId": "00e4W000002LjMoQAK", "SystemModstamp": "2023-10-22T05:59:12.000Z", "AssignedUserCount": 0, "ActiveUserCount": 0}, "emitted_at": 1698150320258}
 {"stream": "ActiveProfileMetric", "data": {"Id": "5H04W00000U3Ph5SAF", "MetricsDate": "2023-10-22", "UserLicenseId": "1004W000001gXv3QAE", "ProfileId": "00e4W000002LjMqQAK", "SystemModstamp": "2023-10-22T05:59:12.000Z", "AssignedUserCount": 0, "ActiveUserCount": 0}, "emitted_at": 1698150320258}
 {"stream": "ActiveProfileMetric", "data": {"Id": "5H04W00000U3Ph6SAF", "MetricsDate": "2023-10-22", "UserLicenseId": "1004W000001gXv4QAE", "ProfileId": "00e4W000002LjMrQAK", "SystemModstamp": "2023-10-22T05:59:12.000Z", "AssignedUserCount": 0, "ActiveUserCount": 0}, "emitted_at": 1698150320259}
-{"stream": "AppDefinition", "data": {"Id": "000000000000000AAA", "DurableId": "06m4W000001ldIZQAY", "Label": "Sales", "MasterLabel": "salesforce", "NamespacePrefix": "standard", "DeveloperName": "Sales", "LogoUrl": "/img/salesforce-noname-logo-v2.svg", "Description": "The world's most popular sales force automation (SFA) solution", "UiType": "Aloha", "NavType": "Standard", "UtilityBar": null, "HeaderColor": "#0070D2", "IsOverrideOrgTheme": false, "IsSmallFormFactorSupported": false, "IsMediumFormFactorSupported": false, "IsLargeFormFactorSupported": false, "IsNavPersonalizationDisabled": false, "IsNavAutoTempTabsDisabled": false, "IsNavTabPersistenceDisabled": false}, "emitted_at": 1697452785550}
-{"stream": "AppDefinition", "data": {"Id": "000000000000000AAA", "DurableId": "06m4W000001ldIdQAI", "Label": "Service", "MasterLabel": "supportforce", "NamespacePrefix": "standard", "DeveloperName": "Service", "LogoUrl": "/img/salesforce-noname-logo-v2.svg", "Description": "Manage customer service with accounts, contacts, cases, and more", "UiType": "Aloha", "NavType": "Standard", "UtilityBar": null, "HeaderColor": "#0070D2", "IsOverrideOrgTheme": false, "IsSmallFormFactorSupported": false, "IsMediumFormFactorSupported": false, "IsLargeFormFactorSupported": true, "IsNavPersonalizationDisabled": false, "IsNavAutoTempTabsDisabled": false, "IsNavTabPersistenceDisabled": false}, "emitted_at": 1697452785551}
-{"stream": "AppDefinition", "data": {"Id": "000000000000000AAA", "DurableId": "06m4W000001ldIeQAI", "Label": "Marketing", "MasterLabel": "Marketing", "NamespacePrefix": "standard", "DeveloperName": "Marketing", "LogoUrl": "/img/salesforce-noname-logo-v2.svg", "Description": "Best-in-class on-demand marketing automation", "UiType": "Aloha", "NavType": "Standard", "UtilityBar": null, "HeaderColor": "#0070D2", "IsOverrideOrgTheme": false, "IsSmallFormFactorSupported": false, "IsMediumFormFactorSupported": false, "IsLargeFormFactorSupported": true, "IsNavPersonalizationDisabled": false, "IsNavAutoTempTabsDisabled": false, "IsNavTabPersistenceDisabled": false}, "emitted_at": 1697452785552}
+{"stream":"AppDefinition","data":{"Id":"000000000000000AAA","DurableId":"06m4W000001ldIZQAY","Label":"Sales","MasterLabel":"salesforce","NamespacePrefix":"standard","DeveloperName":"Sales","LogoUrl":"/img/salesforce-noname-logo-v2.svg","Description":"The world's most popular sales force automation (SFA) solution","UiType":"Aloha","NavType":"Standard","UtilityBar":null,"HeaderColor":"#0070D2","IsOverrideOrgTheme":false,"IsSmallFormFactorSupported":false,"IsMediumFormFactorSupported":false,"IsLargeFormFactorSupported":false,"IsNavPersonalizationDisabled":false,"IsNavAutoTempTabsDisabled":false,"IsNavTabPersistenceDisabled":false},"emitted_at":1708425402368}
+{"stream":"AppDefinition","data":{"Id":"000000000000000AAA","DurableId":"06m4W000001ldIdQAI","Label":"Service","MasterLabel":"supportforce","NamespacePrefix":"standard","DeveloperName":"Service","LogoUrl":"/img/salesforce-noname-logo-v2.svg","Description":"Manage customer service with accounts, contacts, cases, and more","UiType":"Aloha","NavType":"Standard","UtilityBar":null,"HeaderColor":"#0070D2","IsOverrideOrgTheme":false,"IsSmallFormFactorSupported":false,"IsMediumFormFactorSupported":false,"IsLargeFormFactorSupported":true,"IsNavPersonalizationDisabled":false,"IsNavAutoTempTabsDisabled":false,"IsNavTabPersistenceDisabled":false},"emitted_at":1708425402369}
+{"stream":"AppDefinition","data":{"Id":"000000000000000AAA","DurableId":"06m4W000001ldIeQAI","Label":"Marketing CRM Classic","MasterLabel":"Marketing","NamespacePrefix":"standard","DeveloperName":"Marketing","LogoUrl":"/img/salesforce-noname-logo-v2.svg","Description":"Track sales and marketing efforts with CRM objects.","UiType":"Aloha","NavType":"Standard","UtilityBar":null,"HeaderColor":"#0070D2","IsOverrideOrgTheme":false,"IsSmallFormFactorSupported":false,"IsMediumFormFactorSupported":false,"IsLargeFormFactorSupported":true,"IsNavPersonalizationDisabled":false,"IsNavAutoTempTabsDisabled":false,"IsNavTabPersistenceDisabled":false},"emitted_at":1708425402369}
 {"stream": "Asset", "data": {"attributes": {"type": "Asset", "url": "/services/data/v57.0/sobjects/Asset/02i4W00000EkJspQAF"}, "Id": "02i4W00000EkJspQAF", "ContactId": null, "AccountId": "0014W00002DkoWNQAZ", "ParentId": null, "RootAssetId": "02i4W00000EkJspQAF", "Product2Id": null, "ProductCode": null, "IsCompetitorProduct": false, "CreatedDate": "2021-01-18T21:44:57.000+0000", "CreatedById": "0054W00000BZkk0QAD", "LastModifiedDate": "2021-01-18T21:44:57.000+0000", "LastModifiedById": "0054W00000BZkk0QAD", "SystemModstamp": "2021-01-18T21:44:57.000+0000", "IsDeleted": false, "Name": "Radish - Black, Winter, Organic", "SerialNumber": null, "InstallDate": null, "PurchaseDate": null, "UsageEndDate": null, "LifecycleStartDate": null, "LifecycleEndDate": null, "Status": null, "Price": null, "Quantity": null, "Description": null, "OwnerId": "0054W00000BZkk0QAD", "AssetProvidedById": null, "AssetServicedById": null, "IsInternal": false, "AssetLevel": 1, "StockKeepingUnit": null, "HasLifecycleManagement": false, "CurrentMrr": null, "CurrentLifecycleEndDate": null, "CurrentQuantity": null, "CurrentAmount": null, "TotalLifecycleAmount": null, "Street": null, "City": null, "State": null, "PostalCode": null, "Country": null, "Latitude": null, "Longitude": null, "GeocodeAccuracy": null, "Address": null, "LastViewedDate": null, "LastReferencedDate": null}, "emitted_at": 1697452787097}
 {"stream": "Asset", "data": {"attributes": {"type": "Asset", "url": "/services/data/v57.0/sobjects/Asset/02i4W00000EkJsqQAF"}, "Id": "02i4W00000EkJsqQAF", "ContactId": null, "AccountId": "0014W00002DkoW0QAJ", "ParentId": null, "RootAssetId": "02i4W00000EkJsqQAF", "Product2Id": null, "ProductCode": null, "IsCompetitorProduct": false, "CreatedDate": "2021-01-18T21:44:57.000+0000", "CreatedById": "0054W00000BZkk0QAD", "LastModifiedDate": "2021-01-18T21:44:57.000+0000", "LastModifiedById": "0054W00000BZkk0QAD", "SystemModstamp": "2021-01-18T21:44:57.000+0000", "IsDeleted": false, "Name": "Cheese - Valancey", "SerialNumber": null, "InstallDate": null, "PurchaseDate": null, "UsageEndDate": null, "LifecycleStartDate": null, "LifecycleEndDate": null, "Status": null, "Price": null, "Quantity": null, "Description": null, "OwnerId": "0054W00000BZkk0QAD", "AssetProvidedById": null, "AssetServicedById": null, "IsInternal": false, "AssetLevel": 1, "StockKeepingUnit": null, "HasLifecycleManagement": false, "CurrentMrr": null, "CurrentLifecycleEndDate": null, "CurrentQuantity": null, "CurrentAmount": null, "TotalLifecycleAmount": null, "Street": null, "City": null, "State": null, "PostalCode": null, "Country": null, "Latitude": null, "Longitude": null, "GeocodeAccuracy": null, "Address": null, "LastViewedDate": null, "LastReferencedDate": null}, "emitted_at": 1697452787099}
 {"stream": "Asset", "data": {"attributes": {"type": "Asset", "url": "/services/data/v57.0/sobjects/Asset/02i4W00000EkJsrQAF"}, "Id": "02i4W00000EkJsrQAF", "ContactId": null, "AccountId": "0014W00002DkoW5QAJ", "ParentId": null, "RootAssetId": "02i4W00000EkJsrQAF", "Product2Id": null, "ProductCode": null, "IsCompetitorProduct": false, "CreatedDate": "2021-01-18T21:44:57.000+0000", "CreatedById": "0054W00000BZkk0QAD", "LastModifiedDate": "2021-01-18T21:44:57.000+0000", "LastModifiedById": "0054W00000BZkk0QAD", "SystemModstamp": "2021-01-18T21:44:57.000+0000", "IsDeleted": false, "Name": "Truffle Cups Green", "SerialNumber": null, "InstallDate": null, "PurchaseDate": null, "UsageEndDate": null, "LifecycleStartDate": null, "LifecycleEndDate": null, "Status": null, "Price": null, "Quantity": null, "Description": null, "OwnerId": "0054W00000BZkk0QAD", "AssetProvidedById": null, "AssetServicedById": null, "IsInternal": false, "AssetLevel": 1, "StockKeepingUnit": null, "HasLifecycleManagement": false, "CurrentMrr": null, "CurrentLifecycleEndDate": null, "CurrentQuantity": null, "CurrentAmount": null, "TotalLifecycleAmount": null, "Street": null, "City": null, "State": null, "PostalCode": null, "Country": null, "Latitude": null, "Longitude": null, "GeocodeAccuracy": null, "Address": null, "LastViewedDate": null, "LastReferencedDate": null}, "emitted_at": 1697452787100}
diff --git a/airbyte-integrations/connectors/source-salesforce/metadata.yaml b/airbyte-integrations/connectors/source-salesforce/metadata.yaml
index 41b47f060e27..ae18dcd63d4f 100644
--- a/airbyte-integrations/connectors/source-salesforce/metadata.yaml
+++ b/airbyte-integrations/connectors/source-salesforce/metadata.yaml
@@ -6,11 +6,11 @@ data:
     hosts:
       - "*.salesforce.com"
   connectorBuildOptions:
-    baseImage: docker.io/airbyte/python-connector-base:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c
+    baseImage: docker.io/airbyte/python-connector-base:1.2.0@sha256:c22a9d97464b69d6ef01898edf3f8612dc11614f05a84984451dde195f337db9
   connectorSubtype: api
   connectorType: source
   definitionId: b117307c-14b6-41aa-9422-947e34922962
-  dockerImageTag: 2.3.1
+  dockerImageTag: 2.3.2
   dockerRepository: airbyte/source-salesforce
   documentationUrl: https://docs.airbyte.com/integrations/sources/salesforce
   githubIssueLabel: source-salesforce
diff --git a/airbyte-integrations/connectors/source-salesforce/poetry.lock b/airbyte-integrations/connectors/source-salesforce/poetry.lock
index 488d03c625d0..37eb11ff1200 100644
--- a/airbyte-integrations/connectors/source-salesforce/poetry.lock
+++ b/airbyte-integrations/connectors/source-salesforce/poetry.lock
@@ -1,14 +1,14 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.59.2"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.59.2.tar.gz", hash = "sha256:cd8a2b679ddd01ac1db9d42e4326c4b4e815dcaf7e1654cbe327cfce7654f07b"},
-    {file = "airbyte_cdk-0.59.2-py3-none-any.whl", hash = "sha256:90f9144f1519e0c66e260b68be94bb9b8f87130276353073c416df2e62ce7c7e"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
@@ -1197,4 +1197,4 @@ files = [
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "80c233c23a5a4b8daf1d141a0638c805d1e4347cc459a02dbceb19c024d7e2cc"
+content-hash = "2e04a4463d839afab2cd36da228d97580143a8d4ef83c3b80fcb4cb78e836d2b"
diff --git a/airbyte-integrations/connectors/source-salesforce/pyproject.toml b/airbyte-integrations/connectors/source-salesforce/pyproject.toml
index 39ce2054ae5e..f81862b62b1c 100644
--- a/airbyte-integrations/connectors/source-salesforce/pyproject.toml
+++ b/airbyte-integrations/connectors/source-salesforce/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "2.3.1"
+version = "2.3.2"
 name = "source-salesforce"
 description = "Source implementation for Salesforce."
 authors = [ "Airbyte ",]
@@ -18,7 +18,7 @@ include = "source_salesforce"
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
 pandas = "==2.2.0"
-airbyte-cdk = "==0.59.2"
+airbyte-cdk = "^0.63.2"
 
 [tool.poetry.scripts]
 source-salesforce = "source_salesforce.run:run"
diff --git a/airbyte-integrations/connectors/source-salesforce/source_salesforce/source.py b/airbyte-integrations/connectors/source-salesforce/source_salesforce/source.py
index 01f3a74a7d6e..cb2293731d01 100644
--- a/airbyte-integrations/connectors/source-salesforce/source_salesforce/source.py
+++ b/airbyte-integrations/connectors/source-salesforce/source_salesforce/source.py
@@ -22,7 +22,9 @@
 from airbyte_cdk.sources.streams.http.auth import TokenAuthenticator
 from airbyte_cdk.sources.utils.schema_helpers import InternalConfig
 from airbyte_cdk.utils.traced_exception import AirbyteTracedException
+from airbyte_protocol.models import FailureType
 from dateutil.relativedelta import relativedelta
+from pendulum.parsing.exceptions import ParserError
 from requests import codes, exceptions  # type: ignore[import]
 
 from .api import PARENT_SALESFORCE_OBJECTS, UNSUPPORTED_BULK_API_SALESFORCE_OBJECTS, UNSUPPORTED_FILTERING_STREAMS, Salesforce
@@ -49,7 +51,7 @@ class SourceSalesforce(ConcurrentSourceAdapter):
     DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
     START_DATE_OFFSET_IN_YEARS = 2
     MAX_WORKERS = 5
-
+    stop_sync_on_stream_failure = True
     message_repository = InMemoryMessageRepository(Level(AirbyteLogFormatter.level_mapping[logger.level]))
 
     def __init__(self, catalog: Optional[ConfiguredAirbyteCatalog], config: Optional[Mapping[str, Any]], state: Optional[TState], **kwargs):
@@ -71,7 +73,24 @@ def _get_sf_object(config: Mapping[str, Any]) -> Salesforce:
         sf.login()
         return sf
 
+    @staticmethod
+    def _validate_stream_slice_step(stream_slice_step: str):
+        if stream_slice_step:
+            try:
+                duration = pendulum.parse(stream_slice_step)
+                if not isinstance(duration, pendulum.Duration):
+                    message = "Stream slice step Interval should be provided in ISO 8601 format."
+                elif duration < pendulum.Duration(seconds=1):
+                    message = "Stream slice step Interval is too small. It should be no less than 1 second. Please set higher value and try again."
+                else:
+                    return
+                raise ParserError(message)
+            except ParserError as e:
+                internal_message = "Incorrect stream slice step"
+                raise AirbyteTracedException(failure_type=FailureType.config_error, internal_message=internal_message, message=e.args[0])
+
     def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, Optional[str]]:
+        self._validate_stream_slice_step(config.get("stream_slice_step"))
         try:
             salesforce = self._get_sf_object(config)
             salesforce.describe()
@@ -147,6 +166,7 @@ def prepare_stream(cls, stream_name: str, json_schema, sobject_options, sf_objec
         if replication_key and stream_name not in UNSUPPORTED_FILTERING_STREAMS:
             stream_class = incremental
             stream_kwargs["replication_key"] = replication_key
+            stream_kwargs["stream_slice_step"] = config.get("stream_slice_step", "P30D")
         else:
             stream_class = full_refresh
 
diff --git a/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml b/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml
index 642e180c078b..1882e4e66c4a 100644
--- a/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml
+++ b/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml
@@ -60,9 +60,21 @@ connectionSpecification:
       description: Toggle to use Bulk API (this might cause empty fields for some streams)
       default: false
       order: 6
+    stream_slice_step:
+      title: Stream Slice Step for Incremental sync
+      type: string
+      description: The size of the time window (ISO8601 duration) to slice requests.
+      default: P30D
+      order: 7
+      examples:
+        - PT12H
+        - P7D
+        - P30D
+        - P1M
+        - P1Y
     streams_criteria:
       type: array
-      order: 7
+      order: 8
       items:
         type: object
         required:
diff --git a/airbyte-integrations/connectors/source-salesforce/source_salesforce/streams.py b/airbyte-integrations/connectors/source-salesforce/source_salesforce/streams.py
index 9bd81a4d16dd..da5064f8b148 100644
--- a/airbyte-integrations/connectors/source-salesforce/source_salesforce/streams.py
+++ b/airbyte-integrations/connectors/source-salesforce/source_salesforce/streams.py
@@ -11,7 +11,6 @@
 import uuid
 from abc import ABC
 from contextlib import closing
-from datetime import datetime, timedelta
 from typing import Any, Callable, Iterable, List, Mapping, MutableMapping, Optional, Tuple, Type, Union
 
 import pandas as pd
@@ -112,7 +111,7 @@ def get_error_display_message(self, exception: BaseException) -> Optional[str]:
             return f"After {self.max_retries} retries the connector has failed with a network error. It looks like Salesforce API experienced temporary instability, please try again later."
         return super().get_error_display_message(exception)
 
-    def get_start_date_from_state(self, stream_state: Mapping[str, Any] = None) -> datetime:
+    def get_start_date_from_state(self, stream_state: Mapping[str, Any] = None) -> pendulum.DateTime:
         if self.state_converter.is_state_message_compatible(stream_state):
             # stream_state is in the concurrent format
             if stream_state.get("slices", []):
@@ -689,28 +688,34 @@ def transform_empty_string_to_none(instance: Any, schema: Any):
 
 class IncrementalRestSalesforceStream(RestSalesforceStream, ABC):
     state_checkpoint_interval = 500
-    STREAM_SLICE_STEP = 30
     _slice = None
 
-    def __init__(self, replication_key: str, **kwargs):
+    def __init__(self, replication_key: str, stream_slice_step: str = "P30D", **kwargs):
         super().__init__(**kwargs)
         self.replication_key = replication_key
+        self._stream_slice_step = stream_slice_step
 
     def stream_slices(
         self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
     ) -> Iterable[Optional[Mapping[str, Any]]]:
-        start, end = (None, None)
         now = pendulum.now(tz="UTC")
         assert LOOKBACK_SECONDS is not None and LOOKBACK_SECONDS >= 0
-        initial_date = self.get_start_date_from_state(stream_state) - timedelta(seconds=LOOKBACK_SECONDS)
-
-        slice_number = 1
-        while not end == now:
-            start = initial_date.add(days=(slice_number - 1) * self.STREAM_SLICE_STEP)
-            end = min(now, initial_date.add(days=slice_number * self.STREAM_SLICE_STEP))
-            self._slice = {"start_date": start.isoformat(timespec="milliseconds"), "end_date": end.isoformat(timespec="milliseconds")}
-            yield {"start_date": start.isoformat(timespec="milliseconds"), "end_date": end.isoformat(timespec="milliseconds")}
-            slice_number = slice_number + 1
+
+        initial_date = self.get_start_date_from_state(stream_state) - pendulum.Duration(seconds=LOOKBACK_SECONDS)
+        slice_start = initial_date
+        while slice_start < now:
+            slice_end = slice_start + self.stream_slice_step
+            self._slice = {
+                "start_date": slice_start.isoformat(timespec="milliseconds"),
+                "end_date": min(slice_end, now).isoformat(timespec="milliseconds"),
+            }
+            yield self._slice
+
+            slice_start += self.stream_slice_step
+
+    @property
+    def stream_slice_step(self) -> pendulum.Duration:
+        return pendulum.parse(self._stream_slice_step)
 
     def request_params(
         self,
diff --git a/airbyte-integrations/connectors/source-salesforce/unit_tests/api_test.py b/airbyte-integrations/connectors/source-salesforce/unit_tests/api_test.py
index a87f73862dd5..6b31ad9d7d9d 100644
--- a/airbyte-integrations/connectors/source-salesforce/unit_tests/api_test.py
+++ b/airbyte-integrations/connectors/source-salesforce/unit_tests/api_test.py
@@ -2,7 +2,6 @@
 # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
 #
 
-
 import csv
 import io
 import logging
@@ -18,6 +17,7 @@
 from airbyte_cdk.models import AirbyteStream, ConfiguredAirbyteCatalog, ConfiguredAirbyteStream, DestinationSyncMode, SyncMode, Type
 from airbyte_cdk.sources.streams import Stream
 from airbyte_cdk.sources.streams.concurrent.adapters import StreamFacade
+from airbyte_cdk.test.entrypoint_wrapper import read
 from airbyte_cdk.utils import AirbyteTracedException
 from conftest import encoding_symbols_parameters, generate_stream
 from requests.exceptions import HTTPError
@@ -40,6 +40,30 @@
 _ANY_STATE = None
 
 
+@pytest.mark.parametrize(
+    "stream_slice_step, expected_error_message",
+    [
+        ("2023", "Stream slice step Interval should be provided in ISO 8601 format."),
+        ("PT0.1S", "Stream slice step Interval is too small. It should be no less than 1 second."),
+        ("PT1D", "Unable to parse string"),
+        ("P221S", "Unable to parse string"),
+    ],
+    ids=[
+        "incorrect_ISO_8601_format",
+        "too_small_duration_provided",
+        "incorrect_date_format",
+        "incorrect_time_format",
+    ],
+)
+def test_stream_slice_step_validation(stream_slice_step: str, expected_error_message):
+    _ANY_CONFIG.update({"stream_slice_step": stream_slice_step})
+    source = SourceSalesforce(_ANY_CATALOG, _ANY_CONFIG, _ANY_STATE)
+    logger = logging.getLogger("airbyte")
+    with pytest.raises(AirbyteTracedException) as e:
+        source.check_connection(logger, _ANY_CONFIG)
+    assert expected_error_message in e.value.message
+
+
 @pytest.mark.parametrize(
     "login_status_code, login_json_resp, expected_error_msg, is_config_error",
     [
@@ -161,9 +185,6 @@ def test_bulk_sync_pagination(stream_config, stream_api, requests_mock):
     assert result_uri.request_history[2].query == "locator=somelocator_2"
 
 
-
-
-
 def _prepare_mock(m, stream):
     job_id = "fake_job_1"
     m.register_uri("POST", stream.path(), json={"id": job_id})
@@ -386,7 +407,6 @@ def test_rate_limit_bulk(stream_config, stream_api, bulk_catalog, state):
     source = SourceSalesforce(_ANY_CATALOG, _ANY_CONFIG, _ANY_STATE)
     source.streams = Mock()
     source.streams.return_value = streams
-    logger = logging.getLogger("airbyte")
 
     json_response = [{"errorCode": "REQUEST_LIMIT_EXCEEDED", "message": "TotalRequests Limit exceeded."}]
     with requests_mock.Mocker() as m:
@@ -410,17 +430,16 @@ def test_rate_limit_bulk(stream_config, stream_api, bulk_catalog, state):
                 m.register_uri("DELETE", stream.path() + f"/{job_id}")
 
             m.register_uri("POST", stream.path(), creation_responses)
-
-        result = [i for i in source.read(logger=logger, config=stream_config, catalog=bulk_catalog, state=state)]
+        result = read(source=source, config=stream_config, catalog=bulk_catalog, state=state)
         assert stream_1.request_params.called
         assert (
             not stream_2.request_params.called
         ), "The second stream should not be executed, because the first stream finished with Rate Limit."
 
-        records = [item for item in result if item.type == Type.RECORD]
+        records = result.records
         assert len(records) == 6  # stream page size: 6
 
-        state_record = [item for item in result if item.type == Type.STATE][0]
+        state_record = result.state_messages[0]
         assert state_record.state.data["Account"]["LastModifiedDate"] == "2021-10-05T00:00:00+00:00"  # state checkpoint interval is 5.
 
 
@@ -437,13 +456,12 @@ def test_rate_limit_rest(stream_config, stream_api, rest_catalog, state):
     stream_2: IncrementalRestSalesforceStream = generate_stream("AcceptedEventRelation", stream_config, stream_api)
 
     stream_1.state_checkpoint_interval = 3
+    streams = [stream_1, stream_2]
     configure_request_params_mock(stream_1, stream_2)
 
     source = SourceSalesforce(_ANY_CATALOG, _ANY_CONFIG, _ANY_STATE)
     source.streams = Mock()
-    source.streams.return_value = [stream_1, stream_2]
-
-    logger = logging.getLogger("airbyte")
+    source.streams.return_value = streams
 
     next_page_url = "/services/data/v57.0/query/012345"
     response_1 = {
@@ -479,17 +497,17 @@ def test_rate_limit_rest(stream_config, stream_api, rest_catalog, state):
         m.register_uri("GET", stream_1.path(), json=response_1, status_code=200)
         m.register_uri("GET", next_page_url, json=response_2, status_code=403)
 
-        result = [i for i in source.read(logger=logger, config=stream_config, catalog=rest_catalog, state=state)]
+        result = read(source=source, config=stream_config, catalog=rest_catalog, state=state)
 
         assert stream_1.request_params.called
         assert (
             not stream_2.request_params.called
         ), "The second stream should not be executed, because the first stream finished with Rate Limit."
 
-        records = [item for item in result if item.type == Type.RECORD]
+        records = result.records
         assert len(records) == 5
 
-        state_record = [item for item in result if item.type == Type.STATE][0]
+        state_record = result.state_messages[0]
         assert state_record.state.data["KnowledgeArticle"]["LastModifiedDate"] == "2021-11-17T00:00:00+00:00"
 
 
@@ -866,11 +884,14 @@ def test_bulk_stream_error_on_wait_for_job(requests_mock, stream_config, stream_
 
 @freezegun.freeze_time("2023-01-01")
 @pytest.mark.parametrize(
-    "lookback, expect_error",
-    [(None, True), (0, False), (10, False), (-1, True)],
-    ids=["lookback-is-none", "lookback-is-0", "lookback-is-valid", "lookback-is-negative"],
+    "lookback, stream_slice_step, expected_len_stream_slices, expect_error",
+    [(None, "P30D", 0, True), (0, "P30D", 158, False), (10, "P1D", 4732, False), (10, "PT12H", 9463, False), (-1, "P30D", 0, True)],
+    ids=["lookback-is-none", "lookback-is-0-step-30D", "lookback-is-valid-step-1D", "lookback-is-valid-step-12H", "lookback-is-negative"],
 )
-def test_bulk_stream_slices(stream_config_date_format, stream_api, lookback, expect_error):
+def test_bulk_stream_slices(
+    stream_config_date_format, stream_api, lookback, expect_error, stream_slice_step: str, expected_len_stream_slices: int
+):
+    stream_config_date_format["stream_slice_step"] = stream_slice_step
     stream: BulkIncrementalSalesforceStream = generate_stream("FakeBulkStream", stream_config_date_format, stream_api)
     with patch("source_salesforce.streams.LOOKBACK_SECONDS", lookback):
         if expect_error:
@@ -883,14 +904,16 @@ def test_bulk_stream_slices(stream_config_date_format, stream_api, lookback, exp
             today = pendulum.today(tz="UTC")
             start_date = pendulum.parse(stream.start_date, tz="UTC") - timedelta(seconds=lookback)
             while start_date < today:
+                end_date = start_date + stream.stream_slice_step
                 expected_slices.append(
                     {
                         "start_date": start_date.isoformat(timespec="milliseconds"),
-                        "end_date": min(today, start_date.add(days=stream.STREAM_SLICE_STEP)).isoformat(timespec="milliseconds"),
+                        "end_date": min(today, end_date).isoformat(timespec="milliseconds"),
                     }
                 )
-                start_date = start_date.add(days=stream.STREAM_SLICE_STEP)
+                start_date += stream.stream_slice_step
             assert expected_slices == stream_slices
+            assert len(stream_slices) == expected_len_stream_slices
 
 
 @freezegun.freeze_time("2023-04-01")
@@ -955,14 +978,14 @@ def test_bulk_stream_request_params_states(stream_config_date_format, stream_api
 
 def test_request_params_incremental(stream_config_date_format, stream_api):
     stream = generate_stream("ContentDocument", stream_config_date_format, stream_api)
-    params = stream.request_params(stream_state={}, stream_slice={'start_date': '2020', 'end_date': '2021'})
+    params = stream.request_params(stream_state={}, stream_slice={"start_date": "2020", "end_date": "2021"})
 
-    assert params == {'q': 'SELECT LastModifiedDate, Id FROM ContentDocument WHERE LastModifiedDate >= 2020 AND LastModifiedDate < 2021'}
+    assert params == {"q": "SELECT LastModifiedDate, Id FROM ContentDocument WHERE LastModifiedDate >= 2020 AND LastModifiedDate < 2021"}
 
 
 def test_request_params_substream(stream_config_date_format, stream_api):
     stream = generate_stream("ContentDocumentLink", stream_config_date_format, stream_api)
-    params = stream.request_params(stream_state={}, stream_slice={'parents': [{'Id': 1}, {'Id': 2}]})
+    params = stream.request_params(stream_state={}, stream_slice={"parents": [{"Id": 1}, {"Id": 2}]})
 
     assert params == {"q": "SELECT LastModifiedDate, Id FROM ContentDocumentLink WHERE ContentDocumentId IN ('1','2')"}
 
@@ -977,20 +1000,27 @@ def test_stream_slices_for_substream(stream_config, stream_api, requests_mock):
     ContentDocumentLink
     It means that ContentDocumentLink should have 2 slices, with 2 and 1 records in each
     """
-    stream_config['start_date'] = '2023-01-01'
+    stream_config["start_date"] = "2023-01-01"
     stream: BulkSalesforceSubStream = generate_stream("ContentDocumentLink", stream_config, stream_api)
     stream.SLICE_BATCH_SIZE = 2  # each ContentDocumentLink should contain 2 records from parent ContentDocument stream
 
     job_id = "fake_job"
     requests_mock.register_uri("POST", stream.path(), json={"id": job_id})
     requests_mock.register_uri("GET", stream.path() + f"/{job_id}", json={"state": "JobComplete"})
-    requests_mock.register_uri("GET", stream.path() + f"/{job_id}/results", [{"text": "Field1,LastModifiedDate,ID\ntest,2021-11-16,123", "headers": {"Sforce-Locator": "null"}}])
+    requests_mock.register_uri(
+        "GET",
+        stream.path() + f"/{job_id}/results",
+        [{"text": "Field1,LastModifiedDate,ID\ntest,2021-11-16,123", "headers": {"Sforce-Locator": "null"}}],
+    )
     requests_mock.register_uri("DELETE", stream.path() + f"/{job_id}")
 
     stream_slices = list(stream.stream_slices(sync_mode=SyncMode.full_refresh))
     assert stream_slices == [
-         {'parents': [{'Field1': 'test', 'ID': '123', 'LastModifiedDate': '2021-11-16'},
-                      {'Field1': 'test', 'ID': '123', 'LastModifiedDate': '2021-11-16'}]},
-         {'parents': [{'Field1': 'test', 'ID': '123', 'LastModifiedDate': '2021-11-16'}]}
+        {
+            "parents": [
+                {"Field1": "test", "ID": "123", "LastModifiedDate": "2021-11-16"},
+                {"Field1": "test", "ID": "123", "LastModifiedDate": "2021-11-16"},
+            ]
+        },
+        {"parents": [{"Field1": "test", "ID": "123", "LastModifiedDate": "2021-11-16"}]},
     ]
-
diff --git a/airbyte-integrations/connectors/source-salesforce/unit_tests/conftest.py b/airbyte-integrations/connectors/source-salesforce/unit_tests/conftest.py
index eeacdd2235d2..48defd5e5ff2 100644
--- a/airbyte-integrations/connectors/source-salesforce/unit_tests/conftest.py
+++ b/airbyte-integrations/connectors/source-salesforce/unit_tests/conftest.py
@@ -3,10 +3,13 @@
 #
 
 import json
+from typing import List
 from unittest.mock import Mock
 
 import pytest
 from airbyte_cdk.models import ConfiguredAirbyteCatalog
+from airbyte_cdk.test.state_builder import StateBuilder
+from airbyte_protocol.models import AirbyteStateMessage
 from source_salesforce.api import Salesforce
 from source_salesforce.source import SourceSalesforce
 
@@ -32,9 +35,13 @@ def rest_catalog():
 
 
 @pytest.fixture(scope="module")
-def state():
-    state = {"Account": {"LastModifiedDate": "2021-10-01T21:18:20.000Z"}, "Asset": {"SystemModstamp": "2021-10-02T05:08:29.000Z"}}
-    return state
+def state() -> List[AirbyteStateMessage]:
+    return (
+        StateBuilder()
+        .with_stream_state("Account", {"LastModifiedDate": "2021-10-01T21:18:20.000Z"})
+        .with_stream_state("Asset", {"SystemModstamp": "2021-10-02T05:08:29.000Z"})
+        .build()
+    )
 
 
 @pytest.fixture(scope="module")
diff --git a/docs/integrations/sources/salesforce.md b/docs/integrations/sources/salesforce.md
index a1c20615dff4..54edec588742 100644
--- a/docs/integrations/sources/salesforce.md
+++ b/docs/integrations/sources/salesforce.md
@@ -111,7 +111,7 @@ The Salesforce source connector supports the following sync modes:
 - [Incremental Sync - Append](https://docs.airbyte.com/understanding-airbyte/connections/incremental-append)
 - (Recommended)[ Incremental Sync - Append + Deduped](https://docs.airbyte.com/understanding-airbyte/connections/incremental-append-deduped)
 
-## Supported Objects
+## Supported Streams
 
 The Salesforce connector supports reading both Standard Objects and Custom Objects from Salesforce. Each object is read as a separate stream. See a list of all Salesforce Standard Objects [here](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_list.htm).
 
@@ -193,7 +193,8 @@ Now that you have set up the Salesforce source connector, check out the followin
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                                              |
 |:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------|
-| 2.3.1 | 2024-02-12 | [35147](https://github.com/airbytehq/airbyte/pull/35147) | Manage dependencies with Poetry. |
+| 2.3.2   | 2024-02-19 | [35421](https://github.com/airbytehq/airbyte/pull/35421) | Add Stream Slice Step option to specification                                                                                        |
+| 2.3.1   | 2024-02-12 | [35147](https://github.com/airbytehq/airbyte/pull/35147) | Manage dependencies with Poetry.                                                                                                     |
 | 2.3.0   | 2023-12-15 | [33522](https://github.com/airbytehq/airbyte/pull/33522) | Sync streams concurrently in all sync modes                                                                                          |
 | 2.2.2   | 2024-01-04 | [33936](https://github.com/airbytehq/airbyte/pull/33936) | Prepare for airbyte-lib                                                                                                              |
 | 2.2.1   | 2023-12-12 | [33342](https://github.com/airbytehq/airbyte/pull/33342) | Added new ContentDocumentLink stream                                                                                                 |

From 2d80b5676dcf0644ecdccf3aea22454e2c2037de Mon Sep 17 00:00:00 2001
From: Joe Bell 
Date: Thu, 22 Feb 2024 09:17:25 -0800
Subject: [PATCH 24/74] Destination Clickhouse - 1.0, remove normalization
 (#34637)

Co-authored-by: Aaron ("AJ") Steers 
Co-authored-by: Joe Reuter 
Co-authored-by: Obioma Anomnachi 
Co-authored-by: Anatolii Yatsuk <35109939+tolik0@users.noreply.github.com>
Co-authored-by: Maxime Carbonneau-Leclerc <3360483+maxi297@users.noreply.github.com>
Co-authored-by: maxi297 
Co-authored-by: Ryan Waskewich <156025126+rwask@users.noreply.github.com>
Co-authored-by: Catherine Noll 
Co-authored-by: Marius Posta 
Co-authored-by: Edward Gao 
Co-authored-by: Marcos Marx 
Co-authored-by: SatishChGit 
Co-authored-by: evantahler 
Co-authored-by: Rodi Reich Zilberman <867491+rodireich@users.noreply.github.com>
Co-authored-by: Anton Karpets 
Co-authored-by: Christo Grabowski <108154848+ChristoGrab@users.noreply.github.com>
Co-authored-by: Akash Kulkarni 
Co-authored-by: Akash Kulkarni <113392464+akashkulk@users.noreply.github.com>
Co-authored-by: Gireesh Sreepathi 
Co-authored-by: Artem Inzhyyants <36314070+artem1205@users.noreply.github.com>
---
 airbyte-cdk/java/airbyte-cdk/build.gradle     |  22 ++++
 .../base/ssh/SshWrappedDestination.java       |   8 +-
 .../destination/StandardNameTransformer.java  |   1 +
 .../util/ConfiguredCatalogUtil.kt             |  20 ++++
 .../src/main/resources/version.properties     |   2 +-
 .../jdbc/AbstractJdbcDestination.java         |  86 ++++++++-------
 .../typing_deduping/RawOnlySqlGenerator.kt    |  66 +++++++++++
 .../DestinationAcceptanceTest.java            |  31 ++----
 .../typing_deduping/DefaultTyperDeduper.java  |  21 +---
 .../typing_deduping/FutureUtils.java          |   8 +-
 .../typing_deduping/NoOpRawTableTDLock.kt     |  22 ++++
 .../NoOpTyperDeduperWithV1V2Migrations.java   | 103 +++++-------------
 .../typing_deduping/TyperDeduperUtil.kt       |  15 +++
 .../bases/base-normalization/build.gradle     |   6 +-
 .../build.gradle                              |   4 +-
 .../metadata.yaml                             |  16 ++-
 .../ClickhouseDestinationStrictEncrypt.java   |   5 +
 ...estinationStrictEncryptAcceptanceTest.java |   7 +-
 .../destination-clickhouse/build.gradle       |   4 +-
 .../destination-clickhouse/metadata.yaml      |  16 ++-
 .../clickhouse/ClickhouseDestination.java     |  19 +++-
 .../clickhouse/ClickhouseSqlOperations.java   |  37 +++++--
 .../src/main/resources/spec.json              |   8 +-
 .../ClickhouseDestinationAcceptanceTest.java  |   7 +-
 ...shClickhouseDestinationAcceptanceTest.java |   8 +-
 .../clickhouse/ClickhouseDestinationTest.java |  21 ++--
 .../destinations/clickhouse-migrations.md     |  66 +++++++++++
 docs/integrations/destinations/clickhouse.md  |  14 ++-
 28 files changed, 445 insertions(+), 198 deletions(-)
 create mode 100644 airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConfiguredCatalogUtil.kt
 create mode 100644 airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt
 create mode 100644 airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpRawTableTDLock.kt
 create mode 100644 airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TyperDeduperUtil.kt
 create mode 100644 docs/integrations/destinations/clickhouse-migrations.md

diff --git a/airbyte-cdk/java/airbyte-cdk/build.gradle b/airbyte-cdk/java/airbyte-cdk/build.gradle
index f4abc2a918b9..089b72dbc5cd 100644
--- a/airbyte-cdk/java/airbyte-cdk/build.gradle
+++ b/airbyte-cdk/java/airbyte-cdk/build.gradle
@@ -1,13 +1,22 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
+plugins {
+    id 'org.jetbrains.kotlin.jvm' version '1.9.22'
+}
+
 final var cdkVersion = {
     var props = new Properties()
     file("core/src/main/resources/version.properties").withInputStream(props::load)
     return props.getProperty('version', 'undefined')
 }()
 
+
+
 allprojects {
     apply plugin: 'java-library'
     apply plugin: 'maven-publish'
     apply plugin: 'java-test-fixtures'
+    apply plugin: 'org.jetbrains.kotlin.jvm'
 
     group 'io.airbyte.cdk'
 
@@ -44,6 +53,19 @@ allprojects {
                 }
             }
         }
+
+        compileKotlin {
+            compilerOptions {
+                jvmTarget = JvmTarget.JVM_21
+                languageVersion = KotlinVersion.KOTLIN_1_9
+            }
+        }
+        compileTestKotlin {
+            compilerOptions {
+                jvmTarget = JvmTarget.JVM_21
+                languageVersion = KotlinVersion.KOTLIN_1_9
+            }
+        }
     }
 
     project.configurations {
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/ssh/SshWrappedDestination.java b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/ssh/SshWrappedDestination.java
index 826195d3fbcc..f0873bb05edb 100644
--- a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/ssh/SshWrappedDestination.java
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/ssh/SshWrappedDestination.java
@@ -4,7 +4,13 @@
 
 package io.airbyte.cdk.integrations.base.ssh;
 
-import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.*;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.CONNECTION_OPTIONS_KEY;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.GLOBAL_HEARTBEAT_INTERVAL_DEFAULT_IN_MILLIS;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.GLOBAL_HEARTBEAT_INTERVAL_KEY;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.SESSION_HEARTBEAT_INTERVAL_DEFAULT_IN_MILLIS;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.SESSION_HEARTBEAT_INTERVAL_KEY;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.getInstance;
+import static io.airbyte.cdk.integrations.base.ssh.SshTunnel.sshWrap;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/destination/StandardNameTransformer.java b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/destination/StandardNameTransformer.java
index a0bb39cc5d25..cc9c2dc4cd15 100644
--- a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/destination/StandardNameTransformer.java
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/destination/StandardNameTransformer.java
@@ -31,6 +31,7 @@ public String getNamespace(final String namespace) {
   }
 
   @Override
+  // @Deprecated see https://github.com/airbytehq/airbyte/issues/35333
   public String getRawTableName(final String streamName) {
     return convertStreamName("_airbyte_raw_" + streamName);
   }
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConfiguredCatalogUtil.kt b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConfiguredCatalogUtil.kt
new file mode 100644
index 000000000000..42183f51fcbe
--- /dev/null
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConfiguredCatalogUtil.kt
@@ -0,0 +1,20 @@
+package io.airbyte.cdk.integrations.util
+
+import io.airbyte.protocol.models.v0.ConfiguredAirbyteCatalog
+
+/**
+ * For streams in [catalog] which do not have a namespace specified, explicitly set their namespace
+ * to the [defaultNamespace]
+ */
+ fun addDefaultNamespaceToStreams(catalog: ConfiguredAirbyteCatalog, defaultNamespace: String?) {
+     if (defaultNamespace == null) {
+         return
+     }
+    // TODO: This logic exists in all V2 destinations.
+    // This is sad that if we forget to add this, there will be a null pointer during parseCatalog
+    for (catalogStream in catalog.streams) {
+        if (catalogStream.stream.namespace.isNullOrEmpty()) {
+            catalogStream.stream.namespace = defaultNamespace
+        }
+    }
+}
diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
index 955936a54212..1df5d31312c9 100644
--- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
+++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties
@@ -1 +1 @@
-version=0.21.4
+version=0.22.1
diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java
index d25b6ecb4296..f43e1abdea05 100644
--- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java
+++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java
@@ -5,6 +5,7 @@
 package io.airbyte.cdk.integrations.destination.jdbc;
 
 import static io.airbyte.cdk.integrations.base.errors.messages.ErrorMessage.getErrorMessage;
+import static io.airbyte.cdk.integrations.util.ConfiguredCatalogUtilKt.addDefaultNamespaceToStreams;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.annotations.VisibleForTesting;
@@ -40,7 +41,6 @@
 import io.airbyte.protocol.models.v0.AirbyteConnectionStatus.Status;
 import io.airbyte.protocol.models.v0.AirbyteMessage;
 import io.airbyte.protocol.models.v0.ConfiguredAirbyteCatalog;
-import io.airbyte.protocol.models.v0.ConfiguredAirbyteStream;
 import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
@@ -49,7 +49,6 @@
 import java.util.function.Consumer;
 import javax.sql.DataSource;
 import org.apache.commons.lang3.NotImplementedException;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,6 +71,10 @@ protected SqlOperations getSqlOperations() {
     return sqlOperations;
   }
 
+  protected String getConfigSchemaKey() {
+    return "schema";
+  }
+
   public AbstractJdbcDestination(final String driverClass,
                                  final NamingConventionTransformer namingResolver,
                                  final SqlOperations sqlOperations) {
@@ -276,44 +279,16 @@ public SerializedAirbyteMessageConsumer getSerializedMessageConsumer(final JsonN
                                                                        final ConfiguredAirbyteCatalog catalog,
                                                                        final Consumer outputRecordCollector)
       throws Exception {
-    final DataSource dataSource = getDataSource(config);
-    final JdbcDatabase database = getDatabase(dataSource);
+    final JdbcDatabase database = getDatabase(getDataSource(config));
+    final String defaultNamespace;
+    final TyperDeduper typerDeduper;
     if (TypingAndDedupingFlag.isDestinationV2()) {
-      // TODO: This logic exists in all V2 destinations.
-      // This is sad that if we forget to add this, there will be a null pointer during parseCatalog
-      final String defaultNamespace = config.get("schema").asText();
-      for (final ConfiguredAirbyteStream stream : catalog.getStreams()) {
-        if (StringUtils.isEmpty(stream.getStream().getNamespace())) {
-          stream.getStream().setNamespace(defaultNamespace);
-        }
-      }
-      final JdbcSqlGenerator sqlGenerator = getSqlGenerator();
-      final ParsedCatalog parsedCatalog = TypingAndDedupingFlag.getRawNamespaceOverride(RAW_SCHEMA_OVERRIDE)
-          .map(override -> new CatalogParser(sqlGenerator, override))
-          .orElse(new CatalogParser(sqlGenerator))
-          .parseCatalog(catalog);
-      final String databaseName = getDatabaseName(config);
-      final var migrator = new JdbcV1V2Migrator(namingResolver, database, databaseName);
-      final NoopV2TableMigrator v2TableMigrator = new NoopV2TableMigrator();
-      final DestinationHandler destinationHandler = getDestinationHandler(databaseName, database);
-      final boolean disableTypeDedupe = config.has(DISABLE_TYPE_DEDUPE) && config.get(DISABLE_TYPE_DEDUPE).asBoolean(false);
-      final TyperDeduper typerDeduper;
-      if (disableTypeDedupe) {
-        typerDeduper = new NoOpTyperDeduperWithV1V2Migrations<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator,
-            8);
-      } else {
-        typerDeduper =
-            new DefaultTyperDeduper<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator, 8);
-      }
-      return JdbcBufferedConsumerFactory.createAsync(
-          outputRecordCollector,
-          database,
-          sqlOperations,
-          namingResolver,
-          config,
-          catalog,
-          defaultNamespace,
-          typerDeduper);
+      defaultNamespace = config.get(getConfigSchemaKey()).asText();
+      addDefaultNamespaceToStreams(catalog, defaultNamespace);
+      typerDeduper = getV2TyperDeduper(config, catalog, database);
+    } else {
+      defaultNamespace = null;
+      typerDeduper = new NoopTyperDeduper();
     }
     return JdbcBufferedConsumerFactory.createAsync(
         outputRecordCollector,
@@ -322,8 +297,37 @@ public SerializedAirbyteMessageConsumer getSerializedMessageConsumer(final JsonN
         namingResolver,
         config,
         catalog,
-        null,
-        new NoopTyperDeduper());
+        defaultNamespace,
+        typerDeduper);
+  }
+
+  /**
+   * Creates the appropriate TyperDeduper class for the jdbc destination and the user's configuration
+   *
+   * @param config the configuration for the connection
+   * @param catalog the catalog for the connection
+   * @param database a database instance
+   * @return the appropriate TyperDeduper instance for this connection.
+   */
+  private TyperDeduper getV2TyperDeduper(final JsonNode config, final ConfiguredAirbyteCatalog catalog, final JdbcDatabase database) {
+    final JdbcSqlGenerator sqlGenerator = getSqlGenerator();
+    final ParsedCatalog parsedCatalog = TypingAndDedupingFlag.getRawNamespaceOverride(RAW_SCHEMA_OVERRIDE)
+        .map(override -> new CatalogParser(sqlGenerator, override))
+        .orElse(new CatalogParser(sqlGenerator))
+        .parseCatalog(catalog);
+    final String databaseName = getDatabaseName(config);
+    final var migrator = new JdbcV1V2Migrator(namingResolver, database, databaseName);
+    final NoopV2TableMigrator v2TableMigrator = new NoopV2TableMigrator();
+    final DestinationHandler destinationHandler = getDestinationHandler(databaseName, database);
+    final boolean disableTypeDedupe = !config.has(DISABLE_TYPE_DEDUPE) || config.get(DISABLE_TYPE_DEDUPE).asBoolean(false);
+    final TyperDeduper typerDeduper;
+    if (disableTypeDedupe) {
+      typerDeduper = new NoOpTyperDeduperWithV1V2Migrations<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator);
+    } else {
+      typerDeduper =
+          new DefaultTyperDeduper<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator);
+    }
+    return typerDeduper;
   }
 
 }
diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt
new file mode 100644
index 000000000000..17447dbf0833
--- /dev/null
+++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt
@@ -0,0 +1,66 @@
+package io.airbyte.cdk.integrations.destination.jdbc.typing_deduping
+
+import io.airbyte.cdk.integrations.destination.NamingConventionTransformer
+import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition
+import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType
+import io.airbyte.integrations.base.destination.typing_deduping.ColumnId
+import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig
+import org.jooq.Condition
+import org.jooq.DataType
+import org.jooq.Field
+import org.jooq.SQLDialect
+import java.util.*
+
+/**
+ * Some Destinations do not support Typing and Deduping but have the updated raw table format
+ * SqlGenerator implementations are only for "final" tables and are a required input for
+ * TyperDeduper classes. This implementation appeases that requirement but does not implement
+ * any "final" table operations.
+ */
+class RawOnlySqlGenerator(private val namingTransformer: NamingConventionTransformer) :
+    JdbcSqlGenerator(namingTransformer) {
+    override fun getStructType(): DataType<*>? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun getArrayType(): DataType<*>? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun getWidestType(): DataType<*>? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun getDialect(): SQLDialect? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun extractRawDataFields(
+        columns: LinkedHashMap,
+        useExpensiveSaferCasting: Boolean
+    ): List>? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun buildAirbyteMetaColumn(columns: LinkedHashMap): Field<*>? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun cdcDeletedAtNotNullCondition(): Condition? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun getRowNumber(
+        primaryKey: List,
+        cursorField: Optional
+    ): Field? {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+
+    override fun existingSchemaMatchesStreamConfig(
+        stream: StreamConfig,
+        existingTable: TableDefinition
+    ): Boolean {
+        throw NotImplementedError("This Destination does not support final tables")
+    }
+}
diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/DestinationAcceptanceTest.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/DestinationAcceptanceTest.java
index 72231b4b40cf..8094c8fc214c 100644
--- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/DestinationAcceptanceTest.java
+++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/DestinationAcceptanceTest.java
@@ -789,7 +789,7 @@ public void testIncrementalDedupeSync() throws Exception {
         .map(record -> Jsons.deserialize(record, AirbyteMessage.class))
         .collect(Collectors.toList());
     final JsonNode config = getConfig();
-    runSyncAndVerifyStateOutput(config, firstSyncMessages, configuredCatalog, true);
+    runSyncAndVerifyStateOutput(config, firstSyncMessages, configuredCatalog, supportsNormalization());
 
     final List secondSyncMessages = Lists.newArrayList(
         new AirbyteMessage()
@@ -820,7 +820,7 @@ public void testIncrementalDedupeSync() throws Exception {
             .withType(Type.STATE)
             .withState(new AirbyteStateMessage().withData(
                 Jsons.jsonNode(ImmutableMap.of("checkpoint", 2)))));
-    runSyncAndVerifyStateOutput(config, secondSyncMessages, configuredCatalog, true);
+    runSyncAndVerifyStateOutput(config, secondSyncMessages, configuredCatalog, false);
 
     final List expectedMessagesAfterSecondSync = new ArrayList<>();
     expectedMessagesAfterSecondSync.addAll(firstSyncMessages);
@@ -853,22 +853,11 @@ public void testIncrementalDedupeSync() throws Exception {
     final String defaultSchema = getDefaultSchema(config);
     retrieveRawRecordsAndAssertSameMessages(catalog, expectedMessagesAfterSecondSync,
         defaultSchema);
-    final List actualMessages = retrieveNormalizedRecords(catalog,
-        defaultSchema);
-    assertSameMessages(expectedMessages, actualMessages, true);
-  }
-
-  private String generateBigString(final int addExtraCharacters) {
-    final int length = getMaxRecordValueLimit() + addExtraCharacters;
-    return RANDOM
-        .ints('a', 'z' + 1)
-        .limit(length)
-        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
-        .toString();
-  }
-
-  protected int getGenerateBigStringAddExtraCharacters() {
-    return 0;
+    if (normalizationFromDefinition()) {
+      final List actualMessages = retrieveNormalizedRecords(catalog,
+          defaultSchema);
+      assertSameMessages(expectedMessages, actualMessages, true);
+    }
   }
 
   /**
@@ -1347,7 +1336,7 @@ private List runSync(
 
     destination.close();
 
-    if (!runNormalization || (runNormalization && supportsInDestinationNormalization())) {
+    if (!runNormalization || (supportsInDestinationNormalization())) {
       return destinationOutput;
     }
 
@@ -1860,6 +1849,10 @@ public Stream provideArguments(final ExtensionContext conte
 
   }
 
+  private boolean supportsNormalization() {
+    return supportsInDestinationNormalization() || normalizationFromDefinition();
+  }
+
   private static  V0 convertProtocolObject(final V1 v1, final Class klass) {
     return Jsons.object(Jsons.jsonNode(v1), klass);
   }
diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java
index d01f47060ba4..764f888c4e16 100644
--- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java
+++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java
@@ -5,17 +5,16 @@
 package io.airbyte.integrations.base.destination.typing_deduping;
 
 import static io.airbyte.cdk.integrations.base.IntegrationRunner.TYPE_AND_DEDUPE_THREAD_NAME;
-import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.countOfTypingDedupingThreads;
+import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.getCountOfTypeAndDedupeThreads;
 import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.reduceExceptions;
+import static io.airbyte.integrations.base.destination.typing_deduping.TyperDeduperUtilKt.prepareAllSchemas;
 import static java.util.Collections.singleton;
 
-import com.google.common.collect.Streams;
 import io.airbyte.cdk.integrations.destination.StreamSyncSummary;
 import io.airbyte.protocol.models.v0.DestinationSyncMode;
 import io.airbyte.protocol.models.v0.StreamDescriptor;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
@@ -79,8 +78,7 @@ public DefaultTyperDeduper(final SqlGenerator sqlGenerat
                              final DestinationHandler destinationHandler,
                              final ParsedCatalog parsedCatalog,
                              final DestinationV1V2Migrator v1V2Migrator,
-                             final V2TableMigrator v2TableMigrator,
-                             final int defaultThreadCount) {
+                             final V2TableMigrator v2TableMigrator) {
     this.sqlGenerator = sqlGenerator;
     this.destinationHandler = destinationHandler;
     this.parsedCatalog = parsedCatalog;
@@ -90,7 +88,7 @@ public DefaultTyperDeduper(final SqlGenerator sqlGenerat
     this.streamsWithSuccessfulSetup = ConcurrentHashMap.newKeySet(parsedCatalog.streams().size());
     this.tdLocks = new ConcurrentHashMap<>();
     this.internalTdLocks = new ConcurrentHashMap<>();
-    this.executorService = Executors.newFixedThreadPool(countOfTypingDedupingThreads(defaultThreadCount),
+    this.executorService = Executors.newFixedThreadPool(getCountOfTypeAndDedupeThreads(),
         new BasicThreadFactory.Builder().namingPattern(TYPE_AND_DEDUPE_THREAD_NAME).build());
   }
 
@@ -100,18 +98,11 @@ public DefaultTyperDeduper(
                              final ParsedCatalog parsedCatalog,
                              final DestinationV1V2Migrator v1V2Migrator,
                              final int defaultThreadCount) {
-    this(sqlGenerator, destinationHandler, parsedCatalog, v1V2Migrator, new NoopV2TableMigrator(), defaultThreadCount);
+    this(sqlGenerator, destinationHandler, parsedCatalog, v1V2Migrator, new NoopV2TableMigrator());
   }
 
   private void prepareSchemas(final ParsedCatalog parsedCatalog) throws Exception {
-    final var rawSchema = parsedCatalog.streams().stream().map(stream -> stream.id().rawNamespace());
-    final var finalSchema = parsedCatalog.streams().stream().map(stream -> stream.id().finalNamespace());
-    final var createAllSchemasSql = Streams.concat(rawSchema, finalSchema)
-        .filter(Objects::nonNull)
-        .distinct()
-        .map(sqlGenerator::createSchema)
-        .toList();
-    destinationHandler.execute(Sql.concat(createAllSchemasSql));
+    prepareAllSchemas(parsedCatalog, sqlGenerator, destinationHandler);
   }
 
   @Override
diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/FutureUtils.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/FutureUtils.java
index 349437e4acec..3319af8297a0 100644
--- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/FutureUtils.java
+++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/FutureUtils.java
@@ -12,16 +12,18 @@
 
 public class FutureUtils {
 
+  private static final int DEFAULT_TD_THREAD_COUNT = 8;
+
   /**
-   * Allow for configuring the number of typing and deduping threads via an enviornment variable in
+   * Allow for configuring the number of typing and deduping threads via an environment variable in
    * the destination container.
    *
    * @return the number of threads to use in the typing and deduping pool
    */
-  public static int countOfTypingDedupingThreads(final int defaultThreads) {
+  public static int getCountOfTypeAndDedupeThreads() {
     return Optional.ofNullable(System.getenv("TD_THREADS"))
         .map(Integer::valueOf)
-        .orElse(defaultThreads);
+        .orElse(DEFAULT_TD_THREAD_COUNT);
   }
 
   /**
diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpRawTableTDLock.kt b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpRawTableTDLock.kt
new file mode 100644
index 000000000000..9c26e4d605b8
--- /dev/null
+++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpRawTableTDLock.kt
@@ -0,0 +1,22 @@
+package io.airbyte.integrations.base.destination.typing_deduping
+
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.locks.Condition
+import java.util.concurrent.locks.Lock
+
+class NoOpRawTableTDLock: Lock {
+    override fun lock() {}
+
+    override fun lockInterruptibly() {}
+
+    override fun tryLock() = true
+
+    override fun tryLock(time: Long, unit: TimeUnit) = tryLock()
+
+    override fun unlock() {}
+
+    override fun newCondition(): Condition {
+        // Always throw exception to avoid callers from using this path
+        throw UnsupportedOperationException("This lock implementation does not support retrieving a Condition")
+    }
+}
diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java
index f35d1a92356d..1fb3faf59def 100644
--- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java
+++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java
@@ -5,24 +5,23 @@
 package io.airbyte.integrations.base.destination.typing_deduping;
 
 import static io.airbyte.cdk.integrations.base.IntegrationRunner.TYPE_AND_DEDUPE_THREAD_NAME;
-import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.countOfTypingDedupingThreads;
+import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.getCountOfTypeAndDedupeThreads;
 import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.reduceExceptions;
+import static io.airbyte.integrations.base.destination.typing_deduping.TyperDeduperUtilKt.prepareAllSchemas;
 
-import com.google.common.collect.Streams;
 import io.airbyte.cdk.integrations.destination.StreamSyncSummary;
 import io.airbyte.protocol.models.v0.StreamDescriptor;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
+import kotlin.NotImplementedError;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 
 /**
@@ -44,49 +43,42 @@ public NoOpTyperDeduperWithV1V2Migrations(final SqlGenerator destinationHandler,
                                             final ParsedCatalog parsedCatalog,
                                             final DestinationV1V2Migrator v1V2Migrator,
-                                            final V2TableMigrator v2TableMigrator,
-                                            final int defaultThreadCount) {
+                                            final V2TableMigrator v2TableMigrator) {
     this.sqlGenerator = sqlGenerator;
     this.destinationHandler = destinationHandler;
     this.parsedCatalog = parsedCatalog;
     this.v1V2Migrator = v1V2Migrator;
     this.v2TableMigrator = v2TableMigrator;
-    this.executorService = Executors.newFixedThreadPool(countOfTypingDedupingThreads(defaultThreadCount),
+    this.executorService = Executors.newFixedThreadPool(getCountOfTypeAndDedupeThreads(),
         new BasicThreadFactory.Builder().namingPattern(TYPE_AND_DEDUPE_THREAD_NAME).build());
   }
 
-  private void prepareSchemas(final ParsedCatalog parsedCatalog) throws Exception {
-    final var rawSchema = parsedCatalog.streams().stream().map(stream -> stream.id().rawNamespace());
-    final var finalSchema = parsedCatalog.streams().stream().map(stream -> stream.id().finalNamespace());
-    final var createAllSchemasSql = Streams.concat(rawSchema, finalSchema)
-        .filter(Objects::nonNull)
-        .distinct()
-        .map(sqlGenerator::createSchema)
-        .toList();
-    destinationHandler.execute(Sql.concat(createAllSchemasSql));
-  }
-
   @Override
   public void prepareTables() throws Exception {
-    log.info("ensuring schemas exist for prepareTables with V1V2 migrations");
-    prepareSchemas(parsedCatalog);
-    final Set>> prepareTablesTasks = new HashSet<>();
-    for (final StreamConfig stream : parsedCatalog.streams()) {
-      prepareTablesTasks.add(CompletableFuture.supplyAsync(() -> {
-        // Migrate the Raw Tables if this is the first v2 sync after a v1 sync
-        try {
-          log.info("Migrating V1->V2 for stream {}", stream.id());
-          v1V2Migrator.migrateIfNecessary(sqlGenerator, destinationHandler, stream);
-          log.info("Migrating V2 legacy for stream {}", stream.id());
-          v2TableMigrator.migrateIfNecessary(stream);
-          return Optional.empty();
-        } catch (final Exception e) {
-          return Optional.of(e);
-        }
-      }, executorService));
+    try {
+      log.info("Ensuring schemas exist for prepareTables with V1V2 migrations");
+      prepareAllSchemas(parsedCatalog, sqlGenerator, destinationHandler);
+      final Set>> prepareTablesTasks = new HashSet<>();
+      for (final StreamConfig stream : parsedCatalog.streams()) {
+        prepareTablesTasks.add(CompletableFuture.supplyAsync(() -> {
+          // Migrate the Raw Tables if this is the first v2 sync after a v1 sync
+          try {
+            log.info("Migrating V1->V2 for stream {}", stream.id());
+            v1V2Migrator.migrateIfNecessary(sqlGenerator, destinationHandler, stream);
+            log.info("Migrating V2 legacy for stream {}", stream.id());
+            v2TableMigrator.migrateIfNecessary(stream);
+            return Optional.empty();
+          } catch (final Exception e) {
+            return Optional.of(e);
+          }
+        }, executorService));
+      }
+      CompletableFuture.allOf(prepareTablesTasks.toArray(CompletableFuture[]::new)).join();
+      reduceExceptions(prepareTablesTasks, "The following exceptions were thrown attempting to prepare tables:\n");
+    } catch (NotImplementedError | NotImplementedException e) {
+      log.warn(
+          "Could not prepare schemas or tables because this is not implemented for this destination, this should not be required for this destination to succeed");
     }
-    CompletableFuture.allOf(prepareTablesTasks.toArray(CompletableFuture[]::new)).join();
-    reduceExceptions(prepareTablesTasks, "The following exceptions were thrown attempting to prepare tables:\n");
   }
 
   @Override
@@ -96,42 +88,7 @@ public void typeAndDedupe(final String originalNamespace, final String originalN
 
   @Override
   public Lock getRawTableInsertLock(final String originalNamespace, final String originalName) {
-    return new Lock() {
-
-      @Override
-      public void lock() {
-
-      }
-
-      @Override
-      public void lockInterruptibly() {
-
-      }
-
-      @Override
-      public boolean tryLock() {
-        // To mimic NoOp behavior always return true that lock is acquired
-        return true;
-      }
-
-      @Override
-      public boolean tryLock(final long time, final TimeUnit unit) {
-        // To mimic NoOp behavior always return true that lock is acquired
-        return true;
-      }
-
-      @Override
-      public void unlock() {
-
-      }
-
-      @Override
-      public Condition newCondition() {
-        // Always throw exception to avoid callers from using this path
-        throw new UnsupportedOperationException("This lock implementation does not support retrieving a Condition");
-      }
-
-    };
+    return new NoOpRawTableTDLock();
   }
 
   @Override
diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TyperDeduperUtil.kt b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TyperDeduperUtil.kt
new file mode 100644
index 000000000000..c8020d561826
--- /dev/null
+++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TyperDeduperUtil.kt
@@ -0,0 +1,15 @@
+package io.airbyte.integrations.base.destination.typing_deduping
+
+
+/**
+ * Extracts all the "raw" and "final" schemas identified in the [parsedCatalog] and ensures they
+ * exist in the Destination Database.
+ */
+fun  prepareAllSchemas(parsedCatalog: ParsedCatalog, sqlGenerator: SqlGenerator, destinationHandler: DestinationHandler) {
+    val rawSchema = parsedCatalog.streams.mapNotNull { it.id.rawNamespace }
+    val finalSchema = parsedCatalog.streams.mapNotNull { it.id.finalNamespace }
+    val createAllSchemasSql = rawSchema.union(finalSchema)
+        .map { sqlGenerator.createSchema(it) }
+        .toList()
+    destinationHandler.execute(Sql.concat(createAllSchemasSql))
+}
diff --git a/airbyte-integrations/bases/base-normalization/build.gradle b/airbyte-integrations/bases/base-normalization/build.gradle
index 0be8b3f954d4..13f2dd53c9f9 100644
--- a/airbyte-integrations/bases/base-normalization/build.gradle
+++ b/airbyte-integrations/bases/base-normalization/build.gradle
@@ -1,5 +1,3 @@
-import org.apache.tools.ant.taskdefs.condition.Os
-
 plugins {
     id 'airbyte-docker-legacy'
     id 'airbyte-python'
@@ -38,6 +36,10 @@ tasks.named('check').configure {
     dependsOn generate
 }
 
+tasks.named("jar").configure {
+    dependsOn copySshScript
+}
+
 [
         'bigquery',
         'mysql',
diff --git a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/build.gradle b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/build.gradle
index d1a316d740a4..584fd3a0dc72 100644
--- a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/build.gradle
+++ b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/build.gradle
@@ -4,8 +4,8 @@ plugins {
 }
 
 airbyteJavaConnector {
-    cdkVersionRequired = '0.2.0'
-    features = ['db-destinations']
+    cdkVersionRequired = '0.22.1'
+    features = ['db-destinations', 's3-destinations', 'typing-deduping']
     useLocalCdk = false
 }
 
diff --git a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/metadata.yaml b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/metadata.yaml
index b58fc5f5d3e5..c5023258510c 100644
--- a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/metadata.yaml
+++ b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/metadata.yaml
@@ -7,16 +7,22 @@ data:
   connectorSubtype: database
   connectorType: destination
   definitionId: ce0d828e-1dc4-496c-b122-2da42e637e48
-  dockerImageTag: 0.2.5
+  dockerImageTag: 1.0.0
   dockerRepository: airbyte/destination-clickhouse-strict-encrypt
   githubIssueLabel: destination-clickhouse
   icon: clickhouse.svg
   license: MIT
   name: Clickhouse
-  normalizationConfig:
-    normalizationIntegrationType: clickhouse
-    normalizationRepository: airbyte/normalization-clickhouse
-    normalizationTag: 0.4.1
+  releases:
+    breakingChanges:
+      1.0.0:
+        upgradeDeadline: "2024-03-15"
+        message: >
+          This version removes the option to use "normalization" with clickhouse. It also changes
+          the schema and database of Airbyte's "raw" tables to be compatible with the new
+          [Destinations V2](https://docs.airbyte.com/release_notes/upgrading_to_destinations_v2/#what-is-destinations-v2)
+          format. These changes will likely require updates to downstream dbt / SQL models.
+          Selecting `Upgrade` will upgrade **all** connections using this destination at their next sync.
   releaseStage: alpha
   documentationUrl: https://docs.airbyte.com/integrations/destinations/clickhouse
   supportsDbt: false
diff --git a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncrypt.java b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncrypt.java
index 98d998a9e3ef..4efc4db3545c 100644
--- a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncrypt.java
+++ b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncrypt.java
@@ -36,4 +36,9 @@ public static void main(final String[] args) throws Exception {
     LOGGER.info("completed destination: {}", ClickhouseDestinationStrictEncrypt.class);
   }
 
+  @Override
+  public boolean isV2Destination() {
+    return true;
+  }
+
 }
diff --git a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncryptAcceptanceTest.java b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncryptAcceptanceTest.java
index 6769060d4ff1..991ef0e2cde4 100644
--- a/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncryptAcceptanceTest.java
+++ b/airbyte-integrations/connectors/destination-clickhouse-strict-encrypt/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationStrictEncryptAcceptanceTest.java
@@ -21,6 +21,7 @@
 import io.airbyte.cdk.integrations.standardtest.destination.comparator.TestDataComparator;
 import io.airbyte.cdk.integrations.util.HostPortResolver;
 import io.airbyte.commons.json.Jsons;
+import io.airbyte.integrations.base.destination.typing_deduping.StreamId;
 import java.sql.SQLException;
 import java.time.Duration;
 import java.util.ArrayList;
@@ -139,7 +140,7 @@ protected List retrieveRecords(final TestDestinationEnv testEnv,
                                            final String namespace,
                                            final JsonNode streamSchema)
       throws Exception {
-    return retrieveRecordsFromTable(namingResolver.getRawTableName(streamName), namespace)
+    return retrieveRecordsFromTable(StreamId.concatenateRawTableName(namespace, streamName), "airbyte_internal")
         .stream()
         .map(r -> Jsons.deserialize(r.get(JavaBaseConstants.COLUMN_NAME_DATA).asText()))
         .collect(Collectors.toList());
@@ -147,7 +148,9 @@ protected List retrieveRecords(final TestDestinationEnv testEnv,
 
   private List retrieveRecordsFromTable(final String tableName, final String schemaName) throws SQLException {
     final JdbcDatabase jdbcDB = getDatabase(getConfig());
-    final String query = String.format("SELECT * FROM %s.%s ORDER BY %s ASC", schemaName, tableName, JavaBaseConstants.COLUMN_NAME_EMITTED_AT);
+    final var nameTransformer = new StandardNameTransformer();
+    final String query = String.format("SELECT * FROM `%s`.`%s` ORDER BY %s ASC", schemaName, nameTransformer.convertStreamName(tableName),
+        JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT);
     return jdbcDB.queryJsons(query);
   }
 
diff --git a/airbyte-integrations/connectors/destination-clickhouse/build.gradle b/airbyte-integrations/connectors/destination-clickhouse/build.gradle
index 0386841d5f45..25cb081d4263 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/build.gradle
+++ b/airbyte-integrations/connectors/destination-clickhouse/build.gradle
@@ -4,8 +4,8 @@ plugins {
 }
 
 airbyteJavaConnector {
-    cdkVersionRequired = '0.2.0'
-    features = ['db-destinations']
+    cdkVersionRequired = '0.22.1'
+    features = ['db-destinations', 's3-destinations', 'typing-deduping']
     useLocalCdk = false
 }
 
diff --git a/airbyte-integrations/connectors/destination-clickhouse/metadata.yaml b/airbyte-integrations/connectors/destination-clickhouse/metadata.yaml
index cf10ca7aa667..b6cc2b944a79 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/metadata.yaml
+++ b/airbyte-integrations/connectors/destination-clickhouse/metadata.yaml
@@ -2,22 +2,28 @@ data:
   connectorSubtype: database
   connectorType: destination
   definitionId: ce0d828e-1dc4-496c-b122-2da42e637e48
-  dockerImageTag: 0.2.5
+  dockerImageTag: 1.0.0
   dockerRepository: airbyte/destination-clickhouse
   githubIssueLabel: destination-clickhouse
   icon: clickhouse.svg
   license: MIT
   name: Clickhouse
-  normalizationConfig:
-    normalizationIntegrationType: clickhouse
-    normalizationRepository: airbyte/normalization-clickhouse
-    normalizationTag: 0.4.3
   registries:
     cloud:
       dockerRepository: airbyte/destination-clickhouse-strict-encrypt
       enabled: true
     oss:
       enabled: true
+  releases:
+    breakingChanges:
+      1.0.0:
+        upgradeDeadline: "2024-03-15"
+        message: >
+          This version removes the option to use "normalization" with clickhouse. It also changes
+          the schema and database of Airbyte's "raw" tables to be compatible with the new
+          [Destinations V2](https://docs.airbyte.com/release_notes/upgrading_to_destinations_v2/#what-is-destinations-v2)
+          format. These changes will likely require updates to downstream dbt / SQL models.
+          Selecting `Upgrade` will upgrade **all** connections using this destination at their next sync.
   releaseStage: alpha
   documentationUrl: https://docs.airbyte.com/integrations/destinations/clickhouse
   supportsDbt: false
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestination.java b/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestination.java
index 45a9d7cc8f08..77b3347944ca 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestination.java
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestination.java
@@ -16,6 +16,8 @@
 import io.airbyte.cdk.integrations.base.ssh.SshWrappedDestination;
 import io.airbyte.cdk.integrations.destination.NamingConventionTransformer;
 import io.airbyte.cdk.integrations.destination.jdbc.AbstractJdbcDestination;
+import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator;
+import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.RawOnlySqlGenerator;
 import io.airbyte.commons.json.Jsons;
 import io.airbyte.protocol.models.v0.AirbyteConnectionStatus;
 import io.airbyte.protocol.models.v0.AirbyteConnectionStatus.Status;
@@ -87,7 +89,7 @@ public AirbyteConnectionStatus check(final JsonNode config) {
       final JdbcDatabase database = getDatabase(dataSource);
       final NamingConventionTransformer namingResolver = getNamingResolver();
       final String outputSchema = namingResolver.getIdentifier(config.get(JdbcUtils.DATABASE_KEY).asText());
-      attemptSQLCreateAndDropTableOperations(outputSchema, database, namingResolver, getSqlOperations());
+      attemptTableOperations(outputSchema, database, namingResolver, getSqlOperations(), false);
       return new AirbyteConnectionStatus().withStatus(Status.SUCCEEDED);
     } catch (final Exception e) {
       LOGGER.error("Exception while checking connection: ", e);
@@ -115,4 +117,19 @@ public static void main(final String[] args) throws Exception {
     LOGGER.info("completed destination: {}", ClickhouseDestination.class);
   }
 
+  @Override
+  protected JdbcSqlGenerator getSqlGenerator() {
+    return new RawOnlySqlGenerator(new ClickhouseSQLNameTransformer());
+  }
+
+  @Override
+  public boolean isV2Destination() {
+    return true;
+  }
+
+  @Override
+  protected String getConfigSchemaKey() {
+    return "database";
+  }
+
 }
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseSqlOperations.java b/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseSqlOperations.java
index 76d2fa56af89..0d0acf62d5ee 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseSqlOperations.java
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/main/java/io/airbyte/integrations/destination/clickhouse/ClickhouseSqlOperations.java
@@ -10,7 +10,7 @@
 import io.airbyte.cdk.db.jdbc.JdbcDatabase;
 import io.airbyte.cdk.integrations.base.JavaBaseConstants;
 import io.airbyte.cdk.integrations.destination.jdbc.JdbcSqlOperations;
-import io.airbyte.protocol.models.v0.AirbyteRecordMessage;
+import io.airbyte.cdk.integrations.destination_async.partial_messages.PartialAirbyteMessage;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -36,18 +36,22 @@ public boolean isSchemaRequired() {
   @Override
   public String createTableQuery(final JdbcDatabase database, final String schemaName, final String tableName) {
     return String.format(
-        "CREATE TABLE IF NOT EXISTS %s.%s ( \n"
-            + "%s String,\n"
-            + "%s String,\n"
-            + "%s DateTime64(3, 'GMT') DEFAULT now(),\n"
-            + "PRIMARY KEY(%s)\n"
-            + ")\n"
-            + "ENGINE = MergeTree;\n",
+        """
+          CREATE TABLE IF NOT EXISTS `%s`.`%s` (
+          %s String,
+          %s String,
+          %s DateTime64(3, 'GMT') DEFAULT now(),
+          %s DateTime64(3, 'GMT') NULL,
+          PRIMARY KEY(%s)
+          )
+          ENGINE = MergeTree;
+        """,
         schemaName, tableName,
-        JavaBaseConstants.COLUMN_NAME_AB_ID,
+        JavaBaseConstants.COLUMN_NAME_AB_RAW_ID,
         JavaBaseConstants.COLUMN_NAME_DATA,
-        JavaBaseConstants.COLUMN_NAME_EMITTED_AT,
-        JavaBaseConstants.COLUMN_NAME_AB_ID);
+        JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT,
+        JavaBaseConstants.COLUMN_NAME_AB_LOADED_AT,
+        JavaBaseConstants.COLUMN_NAME_AB_RAW_ID);
   }
 
   @Override
@@ -60,7 +64,7 @@ public void executeTransaction(final JdbcDatabase database, final List q
 
   @Override
   public void insertRecordsInternal(final JdbcDatabase database,
-                                    final List records,
+                                    final List records,
                                     final String schemaName,
                                     final String tmpTableName)
       throws SQLException {
@@ -102,4 +106,13 @@ public void insertRecordsInternal(final JdbcDatabase database,
     });
   }
 
+  @Override
+  protected void insertRecordsInternalV2(final JdbcDatabase database,
+                                         final List records,
+                                         final String schemaName,
+                                         final String tableName)
+      throws Exception {
+    insertRecordsInternal(database, records, schemaName, tableName);
+  }
+
 }
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/main/resources/spec.json b/airbyte-integrations/connectors/destination-clickhouse/src/main/resources/spec.json
index 4f3c51333f8a..a86a89f7f746 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/main/resources/spec.json
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/main/resources/spec.json
@@ -3,7 +3,7 @@
   "supportsIncremental": true,
   "supportsNormalization": true,
   "supportsDBT": false,
-  "supported_destination_sync_modes": ["overwrite", "append", "append_dedup"],
+  "supported_destination_sync_modes": ["overwrite", "append"],
   "connectionSpecification": {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "title": "ClickHouse Destination Spec",
@@ -58,6 +58,12 @@
         "type": "boolean",
         "default": false,
         "order": 6
+      },
+      "raw_data_schema": {
+        "type": "string",
+        "description": "The schema to write raw tables into (default: airbyte_internal)",
+        "title": "Raw Table Schema Name",
+        "order": 7
       }
     }
   }
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationAcceptanceTest.java b/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationAcceptanceTest.java
index 5f5c3ae948fa..c7e7d7a5b6a6 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationAcceptanceTest.java
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationAcceptanceTest.java
@@ -21,6 +21,7 @@
 import io.airbyte.cdk.integrations.standardtest.destination.comparator.TestDataComparator;
 import io.airbyte.cdk.integrations.util.HostPortResolver;
 import io.airbyte.commons.json.Jsons;
+import io.airbyte.integrations.base.destination.typing_deduping.StreamId;
 import java.sql.SQLException;
 import java.time.Duration;
 import java.util.HashSet;
@@ -111,7 +112,7 @@ protected List retrieveRecords(final TestDestinationEnv testEnv,
                                            final String namespace,
                                            final JsonNode streamSchema)
       throws Exception {
-    return retrieveRecordsFromTable(namingResolver.getRawTableName(streamName), namespace)
+    return retrieveRecordsFromTable(StreamId.concatenateRawTableName(namespace, streamName), "airbyte_internal")
         .stream()
         .map(r -> Jsons.deserialize(r.get(JavaBaseConstants.COLUMN_NAME_DATA).asText()))
         .collect(Collectors.toList());
@@ -119,7 +120,9 @@ protected List retrieveRecords(final TestDestinationEnv testEnv,
 
   private List retrieveRecordsFromTable(final String tableName, final String schemaName) throws SQLException {
     final JdbcDatabase jdbcDB = getDatabase(getConfig());
-    final String query = String.format("SELECT * FROM %s.%s ORDER BY %s ASC", schemaName, tableName, JavaBaseConstants.COLUMN_NAME_EMITTED_AT);
+    final var nameTransformer = new StandardNameTransformer();
+    final String query = String.format("SELECT * FROM `%s`.`%s` ORDER BY %s ASC", schemaName, nameTransformer.convertStreamName(tableName),
+        JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT);
     return jdbcDB.queryJsons(query);
   }
 
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/SshClickhouseDestinationAcceptanceTest.java b/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/SshClickhouseDestinationAcceptanceTest.java
index c82dfca207c1..163c9a6e36c6 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/SshClickhouseDestinationAcceptanceTest.java
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/test-integration/java/io/airbyte/integrations/destination/clickhouse/SshClickhouseDestinationAcceptanceTest.java
@@ -19,6 +19,7 @@
 import io.airbyte.cdk.integrations.standardtest.destination.argproviders.DataTypeTestArgumentProvider;
 import io.airbyte.cdk.integrations.standardtest.destination.comparator.TestDataComparator;
 import io.airbyte.commons.json.Jsons;
+import io.airbyte.integrations.base.destination.typing_deduping.StreamId;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -85,7 +86,7 @@ protected String getDefaultSchema(final JsonNode config) {
   @Override
   protected JsonNode getConfig() throws Exception {
     return bastion.getTunnelConfig(getTunnelMethod(), bastion.getBasicDbConfigBuider(db, DB_NAME)
-        .put("schema", DB_NAME), false);
+        .put("schema", DB_NAME), true);
   }
 
   @Override
@@ -109,7 +110,7 @@ protected List retrieveRecords(final TestDestinationEnv testEnv,
                                            final String namespace,
                                            final JsonNode streamSchema)
       throws Exception {
-    return retrieveRecordsFromTable(namingResolver.getRawTableName(streamName), namespace)
+    return retrieveRecordsFromTable(StreamId.concatenateRawTableName(namespace, streamName), "airbyte_internal")
         .stream()
         .map(r -> Jsons.deserialize(r.get(JavaBaseConstants.COLUMN_NAME_DATA).asText()))
         .collect(Collectors.toList());
@@ -122,7 +123,8 @@ private List retrieveRecordsFromTable(final String tableName, final St
         JdbcUtils.PORT_LIST_KEY,
         mangledConfig -> {
           final JdbcDatabase database = getDatabase(mangledConfig);
-          final String query = String.format("SELECT * FROM %s.%s ORDER BY %s ASC", schemaName, tableName, JavaBaseConstants.COLUMN_NAME_EMITTED_AT);
+          final String query = String.format("SELECT * FROM `%s`.`%s` ORDER BY %s ASC", schemaName, namingResolver.convertStreamName(tableName),
+              JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT);
           return database.queryJsons(query);
         });
   }
diff --git a/airbyte-integrations/connectors/destination-clickhouse/src/test/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationTest.java b/airbyte-integrations/connectors/destination-clickhouse/src/test/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationTest.java
index 0b05cb932a8e..e414e428e63d 100644
--- a/airbyte-integrations/connectors/destination-clickhouse/src/test/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationTest.java
+++ b/airbyte-integrations/connectors/destination-clickhouse/src/test/java/io/airbyte/integrations/destination/clickhouse/ClickhouseDestinationTest.java
@@ -13,11 +13,13 @@
 import io.airbyte.cdk.db.jdbc.DefaultJdbcDatabase;
 import io.airbyte.cdk.db.jdbc.JdbcDatabase;
 import io.airbyte.cdk.db.jdbc.JdbcUtils;
-import io.airbyte.cdk.integrations.base.AirbyteMessageConsumer;
 import io.airbyte.cdk.integrations.base.Destination;
+import io.airbyte.cdk.integrations.base.DestinationConfig;
+import io.airbyte.cdk.integrations.base.SerializedAirbyteMessageConsumer;
 import io.airbyte.cdk.integrations.destination.StandardNameTransformer;
 import io.airbyte.commons.json.Jsons;
 import io.airbyte.commons.map.MoreMaps;
+import io.airbyte.integrations.base.destination.typing_deduping.StreamId;
 import io.airbyte.protocol.models.Field;
 import io.airbyte.protocol.models.JsonSchemaType;
 import io.airbyte.protocol.models.v0.AirbyteMessage;
@@ -26,6 +28,7 @@
 import io.airbyte.protocol.models.v0.AirbyteStateMessage;
 import io.airbyte.protocol.models.v0.CatalogHelpers;
 import io.airbyte.protocol.models.v0.ConfiguredAirbyteCatalog;
+import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.util.Comparator;
 import java.util.List;
@@ -95,22 +98,26 @@ static void cleanUp() {
   @Test
   void sanityTest() throws Exception {
     final Destination dest = new ClickhouseDestination();
-    final AirbyteMessageConsumer consumer = dest.getConsumer(config, catalog,
+    DestinationConfig.initialize(config, dest.isV2Destination());
+    final SerializedAirbyteMessageConsumer consumer = dest.getSerializedMessageConsumer(config, catalog,
         Destination::defaultOutputRecordCollector);
     final List expectedRecords = generateRecords(10);
 
     consumer.start();
     expectedRecords.forEach(m -> {
       try {
-        consumer.accept(m);
+        final var strMessage = Jsons.jsonNode(m).toString();
+        consumer.accept(strMessage, strMessage.getBytes(StandardCharsets.UTF_8).length);
       } catch (final Exception e) {
         throw new RuntimeException(e);
       }
     });
-    consumer.accept(new AirbyteMessage()
+    final var abMessage = Jsons.jsonNode(new AirbyteMessage()
         .withType(Type.STATE)
         .withState(new AirbyteStateMessage()
-            .withData(Jsons.jsonNode(ImmutableMap.of(DB_NAME + "." + STREAM_NAME, 10)))));
+            .withData(Jsons.jsonNode(ImmutableMap.of(DB_NAME + "." + STREAM_NAME, 10)))))
+        .toString();
+    consumer.accept(abMessage, abMessage.getBytes(StandardCharsets.UTF_8).length);
     consumer.close();
 
     final JdbcDatabase database = new DefaultJdbcDatabase(
@@ -126,8 +133,8 @@ void sanityTest() throws Exception {
 
     final List actualRecords = database.bufferedResultSetQuery(
         connection -> connection.createStatement().executeQuery(
-            String.format("SELECT * FROM %s.%s;", DB_NAME,
-                namingResolver.getRawTableName(STREAM_NAME))),
+            String.format("SELECT * FROM %s.%s;", "airbyte_internal",
+                StreamId.concatenateRawTableName(DB_NAME, STREAM_NAME))),
         JdbcUtils.getDefaultSourceOperations()::rowToJson);
 
     assertEquals(
diff --git a/docs/integrations/destinations/clickhouse-migrations.md b/docs/integrations/destinations/clickhouse-migrations.md
new file mode 100644
index 000000000000..df8590b36a56
--- /dev/null
+++ b/docs/integrations/destinations/clickhouse-migrations.md
@@ -0,0 +1,66 @@
+# Clickhouse Migration Guide
+
+## Upgrading to 1.0.0
+
+This version removes the option to use "normalization" with clickhouse. It also changes
+the schema and database of Airbyte's "raw" tables to be compatible with the new
+[Destinations V2](https://docs.airbyte.com/release_notes/upgrading_to_destinations_v2/#what-is-destinations-v2)
+format. These changes will likely require updates to downstream dbt / SQL models. After this update, 
+Airbyte will only produce the ‘raw’ v2 tables, which store all content in JSON. These changes remove 
+the ability to do deduplicated syncs with Clickhouse.  (Clickhouse has an overview)[[https://clickhouse.com/docs/en/integrations/dbt]]
+for integrating with dbt If you are interested in the Clickhouse destination gaining the full features
+of Destinations V2 (including final tables), click [[https://github.com/airbytehq/airbyte/discussions/35339]] 
+to register your interest.
+
+This upgrade will ignore any existing raw tables and will not migrate any data to the new schema.
+For each stream, you could perform the following query to migrate the data from the old raw table
+to the new raw table:
+
+```sql
+-- assumes your database was 'default'
+-- replace `{{stream_name}}` with replace your stream name
+
+CREATE TABLE airbyte_internal.default_raw__stream_{{stream_name}}
+(
+    `_airbyte_raw_id` String,
+    `_airbyte_extracted_at` DateTime64(3, 'GMT') DEFAULT now(),
+    `_airbyte_loaded_at` DateTime64(3, 'GMT') NULL,
+    `_airbyte_data` String,
+    PRIMARY KEY(`_airbyte_raw_id`)
+)
+ENGINE = MergeTree;
+
+INSERT INTO `airbyte_internal`.`default_raw__stream_{{stream_name}}`
+    SELECT
+        `_airbyte_ab_id` AS "_airbyte_raw_id",
+        `_airbyte_emitted_at` AS "_airbyte_extracted_at",
+        NULL AS "_airbyte_loaded_at",
+        _airbyte_data AS "_airbyte_data"
+    FROM default._airbyte_raw_{{stream_name}};
+```
+
+Airbyte will not delete any of your v1 data.
+
+### Database/Schema and the Internal Schema
+We have split the raw and final tables into their own schemas,
+which in clickhouse is analogous to a `database`. For the Clickhouse destination, this means that
+we will only write into the raw table which will live in the `airbyte_internal` database.
+The tables written into this schema will be prefixed with either the default database provided in 
+the `DB Name` field when configuring clickhouse (but can also be overridden in the connection). You can
+change the "raw" database from the default `airbyte_internal` by supplying a value for 
+`Raw Table Schema Name`.
+
+For Example:
+
+ - DB Name: `default`
+ - Stream Name: `my_stream`
+
+Writes to `airbyte_intneral.default_raw__stream_my_stream`
+
+where as:
+
+ - DB Name: `default`
+ - Stream Name: `my_stream`
+ - Raw Table Schema Name: `raw_data`
+
+Writes to: `raw_data.default_raw__stream_my_stream`
diff --git a/docs/integrations/destinations/clickhouse.md b/docs/integrations/destinations/clickhouse.md
index 02446ba825f6..4495cb79e3da 100644
--- a/docs/integrations/destinations/clickhouse.md
+++ b/docs/integrations/destinations/clickhouse.md
@@ -44,6 +44,17 @@ You can create such a user by running:
 
 ```
 GRANT CREATE ON * TO airbyte_user;
+GRANT CREATE ON default * TO airbyte_user;
+GRANT DROP ON * TO airbyte_user;
+GRANT TRUNCATE ON * TO airbyte_user;
+GRANT INSERT ON * TO airbyte_user;
+GRANT SELECT ON * TO airbyte_user;
+GRANT CREATE DATABASE ON airbyte_internal.* TO airbyte_user;
+GRANT CREATE TABLE ON airbyte_internal.* TO airbyte_user;
+GRANT DROP ON airbyte_internal.* TO airbyte_user;
+GRANT TRUNCATE ON airbyte_internal.* TO airbyte_user;
+GRANT INSERT ON airbyte_internal.* TO airbyte_user;
+GRANT SELECT ON airbyte_internal.* TO airbyte_user;
 ```
 
 You can also use a pre-existing user but we highly recommend creating a dedicated user for Airbyte.
@@ -78,7 +89,8 @@ Therefore, Airbyte ClickHouse destination will create tables and schemas using t
 ## Changelog
 
 | Version | Date       | Pull Request                                               | Subject                                                                                       |
-| :------ | :--------- | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------- |
+|:--------|:-----------| :--------------------------------------------------------- |:----------------------------------------------------------------------------------------------|
+| 1.0.0   | 2024-02-07 | [\#34637](https://github.com/airbytehq/airbyte/pull/34637) | Update the raw table schema                                                                   |
 | 0.2.5   | 2023-06-21 | [\#27555](https://github.com/airbytehq/airbyte/pull/27555) | Reduce image size                                                                             |
 | 0.2.4   | 2023-06-05 | [\#27036](https://github.com/airbytehq/airbyte/pull/27036) | Internal code change for future development (install normalization packages inside connector) |
 | 0.2.3   | 2023-04-04 | [\#24604](https://github.com/airbytehq/airbyte/pull/24604) | Support for destination checkpointing                                                         |

From 0954ad3d3ad2b2e0ede3ab7dd7863d98a6c4f617 Mon Sep 17 00:00:00 2001
From: Artem Inzhyyants <36314070+artem1205@users.noreply.github.com>
Date: Thu, 22 Feb 2024 19:40:44 +0100
Subject: [PATCH 25/74] Airbyte CDK: add interpolation for request options
 (#35485)

Signed-off-by: Artem Inzhyyants 
Co-authored-by: Alexandre Girard 
---
 .../declarative_component_schema.yaml         |   10 +
 .../incremental/datetime_based_cursor.py      |    6 +-
 .../models/declarative_component_schema.py    | 1068 ++++++++---------
 .../list_partition_router.py                  |    2 +-
 .../substream_partition_router.py             |    2 +-
 .../paginators/default_paginator.py           |    4 +-
 .../declarative/requesters/request_option.py  |    9 +-
 .../availability_strategy/__init__.py         |    5 +-
 .../stream/concurrent/cursor/__init__.py      |    2 +-
 .../document_processor_test.py                |    2 +-
 .../vector_db_based/embedder_test.py          |    4 +-
 .../declarative/auth/test_token_auth.py       |    4 +-
 .../test_model_to_component_factory.py        |   48 +-
 .../test_list_partition_router.py             |   51 +-
 .../test_substream_partition_router.py        |   91 +-
 .../paginators/test_default_paginator.py      |   77 +-
 .../paginators/test_request_option.py         |   38 +-
 .../file_types/test_unstructured_parser.py    |  149 ++-
 .../concurrent_incremental_scenarios.py       |  144 ++-
 .../file_based/scenarios/csv_scenarios.py     |   61 +-
 .../scenarios/incremental_scenarios.py        |  134 ++-
 .../file_based/scenarios/jsonl_scenarios.py   |    4 +-
 .../scenarios/unstructured_scenarios.py       |   34 +-
 .../scenarios/user_input_schema_scenarios.py  |    8 +-
 .../stream/concurrent/test_adapters.py        |   16 +-
 .../test_file_based_concurrent_cursor.py      |  144 ++-
 .../stream/test_default_file_based_stream.py  |   32 +-
 .../file_based/test_file_based_scenarios.py   |    1 -
 .../sources/file_based/test_scenarios.py      |    8 +-
 .../scenarios/incremental_scenarios.py        |   15 +-
 .../scenarios/stream_facade_scenarios.py      |    2 +-
 .../test_concurrent_read_processor.py         |   13 +-
 .../sources/streams/concurrent/test_cursor.py |    2 +-
 .../test_datetime_state_converter.py          |  118 +-
 .../concurrent/test_partition_enqueuer.py     |    1 +
 .../concurrent/test_partition_reader.py       |    1 +
 .../sources/test_abstract_source.py           |   44 +-
 .../sources/test_connector_state_manager.py   |    8 +-
 .../test/test_entrypoint_wrapper.py           |   23 +-
 .../python/unit_tests/test_entrypoint.py      |    4 +-
 40 files changed, 1374 insertions(+), 1015 deletions(-)

diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
index 4a5165ca8e7e..7e85d080c601 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
@@ -1898,6 +1898,9 @@ definitions:
         type: string
         examples:
           - segment_id
+        interpolation_context:
+          - config
+          - parameters
       inject_into:
         title: Inject Into
         description: Configures where the descriptor should be set on the HTTP requests. Note that request parameters that are already encoded in the URL path will not be duplicated.
@@ -2154,6 +2157,13 @@ interpolation:
       examples:
         - start_date: 2010-01-01
           api_key: "*****"
+    - title: parameters
+      description: Additional runtime parameters, to be used for string interpolation. Parameters can be passed down from a parent component to its subcomponents using the $parameters key. This can be used to avoid repetitions.
+      type: object
+      examples:
+        - path: "automations"
+          data_export_path: "automations"
+          cursor_field: "updated_at"
     - title: headers
       description: The HTTP headers from the last response received from the API. The object's keys are the header names from the response.
       type: object
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py
index 685f0b7e6876..e2a5f27d1ef3 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py
@@ -247,9 +247,11 @@ def request_kwargs(self) -> Mapping[str, Any]:
     def _get_request_options(self, option_type: RequestOptionType, stream_slice: StreamSlice):
         options = {}
         if self.start_time_option and self.start_time_option.inject_into == option_type:
-            options[self.start_time_option.field_name] = stream_slice.get(self.partition_field_start.eval(self.config))
+            options[self.start_time_option.field_name.eval(config=self.config)] = stream_slice.get(
+                self.partition_field_start.eval(self.config)
+            )
         if self.end_time_option and self.end_time_option.inject_into == option_type:
-            options[self.end_time_option.field_name] = stream_slice.get(self.partition_field_end.eval(self.config))
+            options[self.end_time_option.field_name.eval(config=self.config)] = stream_slice.get(self.partition_field_end.eval(self.config))
         return options
 
     def should_be_synced(self, record: Record) -> bool:
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
index 1ddc137356aa..182c0d5e3690 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
@@ -11,616 +11,610 @@
 
 
 class AuthFlowType(Enum):
-    oauth2_0 = 'oauth2.0'
-    oauth1_0 = 'oauth1.0'
+    oauth2_0 = "oauth2.0"
+    oauth1_0 = "oauth1.0"
 
 
 class BasicHttpAuthenticator(BaseModel):
-    type: Literal['BasicHttpAuthenticator']
+    type: Literal["BasicHttpAuthenticator"]
     username: str = Field(
         ...,
-        description='The username that will be combined with the password, base64 encoded and used to make requests. Fill it in the user inputs.',
+        description="The username that will be combined with the password, base64 encoded and used to make requests. Fill it in the user inputs.",
         examples=["{{ config['username'] }}", "{{ config['api_key'] }}"],
-        title='Username',
+        title="Username",
     )
     password: Optional[str] = Field(
-        '',
-        description='The password that will be combined with the username, base64 encoded and used to make requests. Fill it in the user inputs.',
-        examples=["{{ config['password'] }}", ''],
-        title='Password',
+        "",
+        description="The password that will be combined with the username, base64 encoded and used to make requests. Fill it in the user inputs.",
+        examples=["{{ config['password'] }}", ""],
+        title="Password",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class BearerAuthenticator(BaseModel):
-    type: Literal['BearerAuthenticator']
+    type: Literal["BearerAuthenticator"]
     api_token: str = Field(
         ...,
-        description='Token to inject as request header for authenticating with the API.',
+        description="Token to inject as request header for authenticating with the API.",
         examples=["{{ config['api_key'] }}", "{{ config['token'] }}"],
-        title='Bearer Token',
+        title="Bearer Token",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CheckStream(BaseModel):
-    type: Literal['CheckStream']
+    type: Literal["CheckStream"]
     stream_names: List[str] = Field(
         ...,
-        description='Names of the streams to try reading from when running a check operation.',
-        examples=[['users'], ['users', 'contacts']],
-        title='Stream Names',
+        description="Names of the streams to try reading from when running a check operation.",
+        examples=[["users"], ["users", "contacts"]],
+        title="Stream Names",
     )
 
 
 class ConstantBackoffStrategy(BaseModel):
-    type: Literal['ConstantBackoffStrategy']
+    type: Literal["ConstantBackoffStrategy"]
     backoff_time_in_seconds: Union[float, str] = Field(
         ...,
-        description='Backoff time in seconds.',
+        description="Backoff time in seconds.",
         examples=[30, 30.5, "{{ config['backoff_time'] }}"],
-        title='Backoff Time',
+        title="Backoff Time",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomAuthenticator(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomAuthenticator']
+    type: Literal["CustomAuthenticator"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom authentication strategy. Has to be a sub class of DeclarativeAuthenticator. The format is `source_..`.',
-        examples=['source_railz.components.ShortLivedTokenAuthenticator'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom authentication strategy. Has to be a sub class of DeclarativeAuthenticator. The format is `source_..`.",
+        examples=["source_railz.components.ShortLivedTokenAuthenticator"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomBackoffStrategy(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomBackoffStrategy']
+    type: Literal["CustomBackoffStrategy"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom backoff strategy. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomBackoffStrategy'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom backoff strategy. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomBackoffStrategy"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomErrorHandler(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomErrorHandler']
+    type: Literal["CustomErrorHandler"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom error handler. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomErrorHandler'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom error handler. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomErrorHandler"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomIncrementalSync(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomIncrementalSync']
+    type: Literal["CustomIncrementalSync"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom incremental sync. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomIncrementalSync'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom incremental sync. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomIncrementalSync"],
+        title="Class Name",
     )
     cursor_field: str = Field(
         ...,
-        description='The location of the value on a record that will be used as a bookmark during sync.',
+        description="The location of the value on a record that will be used as a bookmark during sync.",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomPaginationStrategy(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomPaginationStrategy']
+    type: Literal["CustomPaginationStrategy"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom pagination strategy. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomPaginationStrategy'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom pagination strategy. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomPaginationStrategy"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomRecordExtractor(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomRecordExtractor']
+    type: Literal["CustomRecordExtractor"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom record extraction strategy. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomRecordExtractor'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom record extraction strategy. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomRecordExtractor"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomRequester(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomRequester']
+    type: Literal["CustomRequester"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom requester strategy. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomRecordExtractor'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom requester strategy. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomRecordExtractor"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomRetriever(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomRetriever']
+    type: Literal["CustomRetriever"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom retriever strategy. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomRetriever'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom retriever strategy. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomRetriever"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomPartitionRouter(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomPartitionRouter']
+    type: Literal["CustomPartitionRouter"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom partition router. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomPartitionRouter'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom partition router. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomPartitionRouter"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class CustomTransformation(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['CustomTransformation']
+    type: Literal["CustomTransformation"]
     class_name: str = Field(
         ...,
-        description='Fully-qualified name of the class that will be implementing the custom transformation. The format is `source_..`.',
-        examples=['source_railz.components.MyCustomTransformation'],
-        title='Class Name',
+        description="Fully-qualified name of the class that will be implementing the custom transformation. The format is `source_..`.",
+        examples=["source_railz.components.MyCustomTransformation"],
+        title="Class Name",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class RefreshTokenUpdater(BaseModel):
     refresh_token_name: Optional[str] = Field(
-        'refresh_token',
-        description='The name of the property which contains the updated refresh token in the response from the token refresh endpoint.',
-        examples=['refresh_token'],
-        title='Refresh Token Property Name',
+        "refresh_token",
+        description="The name of the property which contains the updated refresh token in the response from the token refresh endpoint.",
+        examples=["refresh_token"],
+        title="Refresh Token Property Name",
     )
     access_token_config_path: Optional[List[str]] = Field(
-        ['credentials', 'access_token'],
-        description='Config path to the access token. Make sure the field actually exists in the config.',
-        examples=[['credentials', 'access_token'], ['access_token']],
-        title='Config Path To Access Token',
+        ["credentials", "access_token"],
+        description="Config path to the access token. Make sure the field actually exists in the config.",
+        examples=[["credentials", "access_token"], ["access_token"]],
+        title="Config Path To Access Token",
     )
     refresh_token_config_path: Optional[List[str]] = Field(
-        ['credentials', 'refresh_token'],
-        description='Config path to the access token. Make sure the field actually exists in the config.',
-        examples=[['credentials', 'refresh_token'], ['refresh_token']],
-        title='Config Path To Refresh Token',
+        ["credentials", "refresh_token"],
+        description="Config path to the access token. Make sure the field actually exists in the config.",
+        examples=[["credentials", "refresh_token"], ["refresh_token"]],
+        title="Config Path To Refresh Token",
     )
     token_expiry_date_config_path: Optional[List[str]] = Field(
-        ['credentials', 'token_expiry_date'],
-        description='Config path to the expiry date. Make sure actually exists in the config.',
-        examples=[['credentials', 'token_expiry_date']],
-        title='Config Path To Expiry Date',
+        ["credentials", "token_expiry_date"],
+        description="Config path to the expiry date. Make sure actually exists in the config.",
+        examples=[["credentials", "token_expiry_date"]],
+        title="Config Path To Expiry Date",
     )
 
 
 class OAuthAuthenticator(BaseModel):
-    type: Literal['OAuthAuthenticator']
+    type: Literal["OAuthAuthenticator"]
     client_id: str = Field(
         ...,
-        description='The OAuth client ID. Fill it in the user inputs.',
+        description="The OAuth client ID. Fill it in the user inputs.",
         examples=["{{ config['client_id }}", "{{ config['credentials']['client_id }}"],
-        title='Client ID',
+        title="Client ID",
     )
     client_secret: str = Field(
         ...,
-        description='The OAuth client secret. Fill it in the user inputs.',
+        description="The OAuth client secret. Fill it in the user inputs.",
         examples=[
             "{{ config['client_secret }}",
             "{{ config['credentials']['client_secret }}",
         ],
-        title='Client Secret',
+        title="Client Secret",
     )
     refresh_token: Optional[str] = Field(
         None,
-        description='Credential artifact used to get a new access token.',
+        description="Credential artifact used to get a new access token.",
         examples=[
             "{{ config['refresh_token'] }}",
             "{{ config['credentials]['refresh_token'] }}",
         ],
-        title='Refresh Token',
+        title="Refresh Token",
     )
     token_refresh_endpoint: str = Field(
         ...,
-        description='The full URL to call to obtain a new access token.',
-        examples=['https://connect.squareup.com/oauth2/token'],
-        title='Token Refresh Endpoint',
+        description="The full URL to call to obtain a new access token.",
+        examples=["https://connect.squareup.com/oauth2/token"],
+        title="Token Refresh Endpoint",
     )
     access_token_name: Optional[str] = Field(
-        'access_token',
-        description='The name of the property which contains the access token in the response from the token refresh endpoint.',
-        examples=['access_token'],
-        title='Access Token Property Name',
+        "access_token",
+        description="The name of the property which contains the access token in the response from the token refresh endpoint.",
+        examples=["access_token"],
+        title="Access Token Property Name",
     )
     expires_in_name: Optional[str] = Field(
-        'expires_in',
-        description='The name of the property which contains the expiry date in the response from the token refresh endpoint.',
-        examples=['expires_in'],
-        title='Token Expiry Property Name',
+        "expires_in",
+        description="The name of the property which contains the expiry date in the response from the token refresh endpoint.",
+        examples=["expires_in"],
+        title="Token Expiry Property Name",
     )
     grant_type: Optional[str] = Field(
-        'refresh_token',
-        description='Specifies the OAuth2 grant type. If set to refresh_token, the refresh_token needs to be provided as well. For client_credentials, only client id and secret are required. Other grant types are not officially supported.',
-        examples=['refresh_token', 'client_credentials'],
-        title='Grant Type',
+        "refresh_token",
+        description="Specifies the OAuth2 grant type. If set to refresh_token, the refresh_token needs to be provided as well. For client_credentials, only client id and secret are required. Other grant types are not officially supported.",
+        examples=["refresh_token", "client_credentials"],
+        title="Grant Type",
     )
     refresh_request_body: Optional[Dict[str, Any]] = Field(
         None,
-        description='Body of the request sent to get a new access token.',
+        description="Body of the request sent to get a new access token.",
         examples=[
             {
-                'applicationId': "{{ config['application_id'] }}",
-                'applicationSecret': "{{ config['application_secret'] }}",
-                'token': "{{ config['token'] }}",
+                "applicationId": "{{ config['application_id'] }}",
+                "applicationSecret": "{{ config['application_secret'] }}",
+                "token": "{{ config['token'] }}",
             }
         ],
-        title='Refresh Request Body',
+        title="Refresh Request Body",
     )
     scopes: Optional[List[str]] = Field(
         None,
-        description='List of scopes that should be granted to the access token.',
-        examples=[
-            ['crm.list.read', 'crm.objects.contacts.read', 'crm.schema.contacts.read']
-        ],
-        title='Scopes',
+        description="List of scopes that should be granted to the access token.",
+        examples=[["crm.list.read", "crm.objects.contacts.read", "crm.schema.contacts.read"]],
+        title="Scopes",
     )
     token_expiry_date: Optional[str] = Field(
         None,
-        description='The access token expiry date.',
-        examples=['2023-04-06T07:12:10.421833+00:00', 1680842386],
-        title='Token Expiry Date',
+        description="The access token expiry date.",
+        examples=["2023-04-06T07:12:10.421833+00:00", 1680842386],
+        title="Token Expiry Date",
     )
     token_expiry_date_format: Optional[str] = Field(
         None,
-        description='The format of the time to expiration datetime. Provide it if the time is returned as a date-time string instead of seconds.',
-        examples=['%Y-%m-%d %H:%M:%S.%f+00:00'],
-        title='Token Expiry Date Format',
+        description="The format of the time to expiration datetime. Provide it if the time is returned as a date-time string instead of seconds.",
+        examples=["%Y-%m-%d %H:%M:%S.%f+00:00"],
+        title="Token Expiry Date Format",
     )
     refresh_token_updater: Optional[RefreshTokenUpdater] = Field(
         None,
-        description='When the token updater is defined, new refresh tokens, access tokens and the access token expiry date are written back from the authentication response to the config object. This is important if the refresh token can only used once.',
-        title='Token Updater',
+        description="When the token updater is defined, new refresh tokens, access tokens and the access token expiry date are written back from the authentication response to the config object. This is important if the refresh token can only used once.",
+        title="Token Updater",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class ExponentialBackoffStrategy(BaseModel):
-    type: Literal['ExponentialBackoffStrategy']
+    type: Literal["ExponentialBackoffStrategy"]
     factor: Optional[Union[float, str]] = Field(
         5,
-        description='Multiplicative constant applied on each retry.',
-        examples=[5, 5.5, '10'],
-        title='Factor',
+        description="Multiplicative constant applied on each retry.",
+        examples=[5, 5.5, "10"],
+        title="Factor",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SessionTokenRequestBearerAuthenticator(BaseModel):
-    type: Literal['Bearer']
+    type: Literal["Bearer"]
 
 
 class HttpMethod(Enum):
-    GET = 'GET'
-    POST = 'POST'
+    GET = "GET"
+    POST = "POST"
 
 
 class Action(Enum):
-    SUCCESS = 'SUCCESS'
-    FAIL = 'FAIL'
-    RETRY = 'RETRY'
-    IGNORE = 'IGNORE'
+    SUCCESS = "SUCCESS"
+    FAIL = "FAIL"
+    RETRY = "RETRY"
+    IGNORE = "IGNORE"
 
 
 class HttpResponseFilter(BaseModel):
-    type: Literal['HttpResponseFilter']
+    type: Literal["HttpResponseFilter"]
     action: Action = Field(
         ...,
-        description='Action to execute if a response matches the filter.',
-        examples=['SUCCESS', 'FAIL', 'RETRY', 'IGNORE'],
-        title='Action',
+        description="Action to execute if a response matches the filter.",
+        examples=["SUCCESS", "FAIL", "RETRY", "IGNORE"],
+        title="Action",
     )
     error_message: Optional[str] = Field(
         None,
-        description='Error Message to display if the response matches the filter.',
-        title='Error Message',
+        description="Error Message to display if the response matches the filter.",
+        title="Error Message",
     )
     error_message_contains: Optional[str] = Field(
         None,
-        description='Match the response if its error message contains the substring.',
-        example=['This API operation is not enabled for this site'],
-        title='Error Message Substring',
+        description="Match the response if its error message contains the substring.",
+        example=["This API operation is not enabled for this site"],
+        title="Error Message Substring",
     )
     http_codes: Optional[List[int]] = Field(
         None,
-        description='Match the response if its HTTP code is included in this list.',
+        description="Match the response if its HTTP code is included in this list.",
         examples=[[420, 429], [500]],
-        title='HTTP Codes',
+        title="HTTP Codes",
     )
     predicate: Optional[str] = Field(
         None,
-        description='Match the response if the predicate evaluates to true.',
+        description="Match the response if the predicate evaluates to true.",
         examples=[
             "{{ 'Too much requests' in response }}",
             "{{ 'error_code' in response and response['error_code'] == 'ComplexityException' }}",
         ],
-        title='Predicate',
+        title="Predicate",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class InlineSchemaLoader(BaseModel):
-    type: Literal['InlineSchemaLoader']
+    type: Literal["InlineSchemaLoader"]
     schema_: Optional[Dict[str, Any]] = Field(
         None,
-        alias='schema',
+        alias="schema",
         description='Describes a streams\' schema. Refer to the Data Types documentation for more details on which types are valid.',
-        title='Schema',
+        title="Schema",
     )
 
 
 class JsonFileSchemaLoader(BaseModel):
-    type: Literal['JsonFileSchemaLoader']
+    type: Literal["JsonFileSchemaLoader"]
     file_path: Optional[str] = Field(
         None,
         description="Path to the JSON file defining the schema. The path is relative to the connector module's root.",
-        example=['./schemas/users.json'],
-        title='File Path',
+        example=["./schemas/users.json"],
+        title="File Path",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class JsonDecoder(BaseModel):
-    type: Literal['JsonDecoder']
+    type: Literal["JsonDecoder"]
 
 
 class MinMaxDatetime(BaseModel):
-    type: Literal['MinMaxDatetime']
+    type: Literal["MinMaxDatetime"]
     datetime: str = Field(
         ...,
-        description='Datetime value.',
-        examples=['2021-01-01', '2021-01-01T00:00:00Z', "{{ config['start_time'] }}"],
-        title='Datetime',
+        description="Datetime value.",
+        examples=["2021-01-01", "2021-01-01T00:00:00Z", "{{ config['start_time'] }}"],
+        title="Datetime",
     )
     datetime_format: Optional[str] = Field(
-        '',
+        "",
         description='Format of the datetime value. Defaults to "%Y-%m-%dT%H:%M:%S.%f%z" if left empty. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:\n  * **%s**: Epoch unix timestamp - `1686218963`\n  * **%ms**: Epoch unix timestamp - `1686218963123`\n  * **%a**: Weekday (abbreviated) - `Sun`\n  * **%A**: Weekday (full) - `Sunday`\n  * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n  * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n  * **%b**: Month (abbreviated) - `Jan`\n  * **%B**: Month (full) - `January`\n  * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n  * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n  * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n  * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n  * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n  * **%p**: AM/PM indicator\n  * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n  * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n  * **%f**: Microsecond (zero-padded to 6 digits) - `000000`, `000001`, ..., `999999`\n  * **%z**: UTC offset - `(empty)`, `+0000`, `-04:00`\n  * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n  * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n  * **%U**: Week number of the year (Sunday as first day) - `00`, `01`, ..., `53`\n  * **%W**: Week number of the year (Monday as first day) - `00`, `01`, ..., `53`\n  * **%c**: Date and time representation - `Tue Aug 16 21:30:00 1988`\n  * **%x**: Date representation - `08/16/1988`\n  * **%X**: Time representation - `21:30:00`\n  * **%%**: Literal \'%\' character\n\n  Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n',
-        examples=['%Y-%m-%dT%H:%M:%S.%f%z', '%Y-%m-%d', '%s'],
-        title='Datetime Format',
+        examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s"],
+        title="Datetime Format",
     )
     max_datetime: Optional[str] = Field(
         None,
-        description='Ceiling applied on the datetime value. Must be formatted with the datetime_format field.',
-        examples=['2021-01-01T00:00:00Z', '2021-01-01'],
-        title='Max Datetime',
+        description="Ceiling applied on the datetime value. Must be formatted with the datetime_format field.",
+        examples=["2021-01-01T00:00:00Z", "2021-01-01"],
+        title="Max Datetime",
     )
     min_datetime: Optional[str] = Field(
         None,
-        description='Floor applied on the datetime value. Must be formatted with the datetime_format field.',
-        examples=['2010-01-01T00:00:00Z', '2010-01-01'],
-        title='Min Datetime',
+        description="Floor applied on the datetime value. Must be formatted with the datetime_format field.",
+        examples=["2010-01-01T00:00:00Z", "2010-01-01"],
+        title="Min Datetime",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class NoAuth(BaseModel):
-    type: Literal['NoAuth']
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    type: Literal["NoAuth"]
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class NoPagination(BaseModel):
-    type: Literal['NoPagination']
+    type: Literal["NoPagination"]
 
 
 class OAuthConfigSpecification(BaseModel):
     class Config:
         extra = Extra.allow
 
-    oauth_user_input_from_connector_config_specification: Optional[
-        Dict[str, Any]
-    ] = Field(
+    oauth_user_input_from_connector_config_specification: Optional[Dict[str, Any]] = Field(
         None,
         description="OAuth specific blob. This is a Json Schema used to validate Json configurations used as input to OAuth.\nMust be a valid non-nested JSON that refers to properties from ConnectorSpecification.connectionSpecification\nusing special annotation 'path_in_connector_config'.\nThese are input values the user is entering through the UI to authenticate to the connector, that might also shared\nas inputs for syncing data via the connector.\nExamples:\nif no connector values is shared during oauth flow, oauth_user_input_from_connector_config_specification=[]\nif connector values such as 'app_id' inside the top level are used to generate the API url for the oauth flow,\n  oauth_user_input_from_connector_config_specification={\n    app_id: {\n      type: string\n      path_in_connector_config: ['app_id']\n    }\n  }\nif connector values such as 'info.app_id' nested inside another object are used to generate the API url for the oauth flow,\n  oauth_user_input_from_connector_config_specification={\n    app_id: {\n      type: string\n      path_in_connector_config: ['info', 'app_id']\n    }\n  }",
         examples=[
-            {'app_id': {'type': 'string', 'path_in_connector_config': ['app_id']}},
+            {"app_id": {"type": "string", "path_in_connector_config": ["app_id"]}},
             {
-                'app_id': {
-                    'type': 'string',
-                    'path_in_connector_config': ['info', 'app_id'],
+                "app_id": {
+                    "type": "string",
+                    "path_in_connector_config": ["info", "app_id"],
                 }
             },
         ],
-        title='OAuth user input',
+        title="OAuth user input",
     )
     complete_oauth_output_specification: Optional[Dict[str, Any]] = Field(
         None,
         description="OAuth specific blob. This is a Json Schema used to validate Json configurations produced by the OAuth flows as they are\nreturned by the distant OAuth APIs.\nMust be a valid JSON describing the fields to merge back to `ConnectorSpecification.connectionSpecification`.\nFor each field, a special annotation `path_in_connector_config` can be specified to determine where to merge it,\nExamples:\n    complete_oauth_output_specification={\n      refresh_token: {\n        type: string,\n        path_in_connector_config: ['credentials', 'refresh_token']\n      }\n    }",
         examples=[
             {
-                'refresh_token': {
-                    'type': 'string,',
-                    'path_in_connector_config': ['credentials', 'refresh_token'],
+                "refresh_token": {
+                    "type": "string,",
+                    "path_in_connector_config": ["credentials", "refresh_token"],
                 }
             }
         ],
-        title='OAuth output specification',
+        title="OAuth output specification",
     )
     complete_oauth_server_input_specification: Optional[Dict[str, Any]] = Field(
         None,
-        description='OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations.\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nserver when completing an OAuth flow (typically exchanging an auth code for refresh token).\nExamples:\n    complete_oauth_server_input_specification={\n      client_id: {\n        type: string\n      },\n      client_secret: {\n        type: string\n      }\n    }',
-        examples=[
-            {'client_id': {'type': 'string'}, 'client_secret': {'type': 'string'}}
-        ],
-        title='OAuth input specification',
+        description="OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations.\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nserver when completing an OAuth flow (typically exchanging an auth code for refresh token).\nExamples:\n    complete_oauth_server_input_specification={\n      client_id: {\n        type: string\n      },\n      client_secret: {\n        type: string\n      }\n    }",
+        examples=[{"client_id": {"type": "string"}, "client_secret": {"type": "string"}}],
+        title="OAuth input specification",
     )
     complete_oauth_server_output_specification: Optional[Dict[str, Any]] = Field(
         None,
         description="OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations that\nalso need to be merged back into the connector configuration at runtime.\nThis is a subset configuration of `complete_oauth_server_input_specification` that filters fields out to retain only the ones that\nare necessary for the connector to function with OAuth. (some fields could be used during oauth flows but not needed afterwards, therefore\nthey would be listed in the `complete_oauth_server_input_specification` but not `complete_oauth_server_output_specification`)\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nconnector when using OAuth flow APIs.\nThese fields are to be merged back to `ConnectorSpecification.connectionSpecification`.\nFor each field, a special annotation `path_in_connector_config` can be specified to determine where to merge it,\nExamples:\n      complete_oauth_server_output_specification={\n        client_id: {\n          type: string,\n          path_in_connector_config: ['credentials', 'client_id']\n        },\n        client_secret: {\n          type: string,\n          path_in_connector_config: ['credentials', 'client_secret']\n        }\n      }",
         examples=[
             {
-                'client_id': {
-                    'type': 'string,',
-                    'path_in_connector_config': ['credentials', 'client_id'],
+                "client_id": {
+                    "type": "string,",
+                    "path_in_connector_config": ["credentials", "client_id"],
                 },
-                'client_secret': {
-                    'type': 'string,',
-                    'path_in_connector_config': ['credentials', 'client_secret'],
+                "client_secret": {
+                    "type": "string,",
+                    "path_in_connector_config": ["credentials", "client_secret"],
                 },
             }
         ],
-        title='OAuth server output specification',
+        title="OAuth server output specification",
     )
 
 
 class OffsetIncrement(BaseModel):
-    type: Literal['OffsetIncrement']
+    type: Literal["OffsetIncrement"]
     page_size: Optional[Union[int, str]] = Field(
         None,
-        description='The number of records to include in each pages.',
+        description="The number of records to include in each pages.",
         examples=[100, "{{ config['page_size'] }}"],
-        title='Limit',
+        title="Limit",
     )
     inject_on_first_request: Optional[bool] = Field(
         False,
-        description='Using the `offset` with value `0` during the first request',
-        title='Inject Offset',
+        description="Using the `offset` with value `0` during the first request",
+        title="Inject Offset",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class PageIncrement(BaseModel):
-    type: Literal['PageIncrement']
+    type: Literal["PageIncrement"]
     page_size: Optional[int] = Field(
         None,
-        description='The number of records to include in each pages.',
-        examples=[100, '100'],
-        title='Page Size',
+        description="The number of records to include in each pages.",
+        examples=[100, "100"],
+        title="Page Size",
     )
     start_from_page: Optional[int] = Field(
         0,
-        description='Index of the first page to request.',
+        description="Index of the first page to request.",
         examples=[0, 1],
-        title='Start From Page',
+        title="Start From Page",
     )
     inject_on_first_request: Optional[bool] = Field(
         False,
-        description='Using the `page number` with value defined by `start_from_page` during the first request',
-        title='Inject Page Number',
+        description="Using the `page number` with value defined by `start_from_page` during the first request",
+        title="Inject Page Number",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class PrimaryKey(BaseModel):
     __root__: Union[str, List[str], List[List[str]]] = Field(
         ...,
-        description='The stream field to be used to distinguish unique records. Can either be a single field, an array of fields representing a composite key, or an array of arrays representing a composite key where the fields are nested fields.',
-        examples=['id', ['code', 'type']],
-        title='Primary Key',
+        description="The stream field to be used to distinguish unique records. Can either be a single field, an array of fields representing a composite key, or an array of arrays representing a composite key where the fields are nested fields.",
+        examples=["id", ["code", "type"]],
+        title="Primary Key",
     )
 
 
 class RecordFilter(BaseModel):
-    type: Literal['RecordFilter']
+    type: Literal["RecordFilter"]
     condition: Optional[str] = Field(
-        '',
-        description='The predicate to filter a record. Records will be removed if evaluated to False.',
+        "",
+        description="The predicate to filter a record. Records will be removed if evaluated to False.",
         examples=[
             "{{ record['created_at'] >= stream_interval['start_time'] }}",
             "{{ record.status in ['active', 'expired'] }}",
         ],
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SchemaNormalization(Enum):
-    None_ = 'None'
-    Default = 'Default'
+    None_ = "None"
+    Default = "Default"
 
 
 class RemoveFields(BaseModel):
-    type: Literal['RemoveFields']
+    type: Literal["RemoveFields"]
     condition: Optional[str] = Field(
-        '',
+        "",
         description="The predicate to filter a property by a property value. Property will be removed if it is empty OR expression is evaluated to True.",
         examples=[
             "{{ property|string == '' }}",
-            '{{ property is integer }}',
-            '{{ property|length > 5 }}',
+            "{{ property is integer }}",
+            "{{ property|length > 5 }}",
             "{{ property == 'some_string_to_match' }}",
         ],
     )
     field_pointers: List[List[str]] = Field(
         ...,
-        description='Array of paths defining the field to remove. Each item is an array whose field describe the path of a field to remove.',
-        examples=[['tags'], [['content', 'html'], ['content', 'plain_text']]],
-        title='Field Paths',
+        description="Array of paths defining the field to remove. Each item is an array whose field describe the path of a field to remove.",
+        examples=[["tags"], [["content", "html"], ["content", "plain_text"]]],
+        title="Field Paths",
     )
 
 
 class RequestPath(BaseModel):
-    type: Literal['RequestPath']
+    type: Literal["RequestPath"]
 
 
 class InjectInto(Enum):
-    request_parameter = 'request_parameter'
-    header = 'header'
-    body_data = 'body_data'
-    body_json = 'body_json'
+    request_parameter = "request_parameter"
+    header = "header"
+    body_data = "body_data"
+    body_json = "body_json"
 
 
 class RequestOption(BaseModel):
-    type: Literal['RequestOption']
+    type: Literal["RequestOption"]
     field_name: str = Field(
         ...,
-        description='Configures which key should be used in the location that the descriptor is being injected into',
-        examples=['segment_id'],
-        title='Request Option',
+        description="Configures which key should be used in the location that the descriptor is being injected into",
+        examples=["segment_id"],
+        title="Request Option",
     )
     inject_into: InjectInto = Field(
         ...,
-        description='Configures where the descriptor should be set on the HTTP requests. Note that request parameters that are already encoded in the URL path will not be duplicated.',
-        examples=['request_parameter', 'header', 'body_data', 'body_json'],
-        title='Inject Into',
+        description="Configures where the descriptor should be set on the HTTP requests. Note that request parameters that are already encoded in the URL path will not be duplicated.",
+        examples=["request_parameter", "header", "body_data", "body_json"],
+        title="Inject Into",
     )
 
 
@@ -632,106 +626,106 @@ class Config:
 
 
 class LegacySessionTokenAuthenticator(BaseModel):
-    type: Literal['LegacySessionTokenAuthenticator']
+    type: Literal["LegacySessionTokenAuthenticator"]
     header: str = Field(
         ...,
-        description='The name of the session token header that will be injected in the request',
-        examples=['X-Session'],
-        title='Session Request Header',
+        description="The name of the session token header that will be injected in the request",
+        examples=["X-Session"],
+        title="Session Request Header",
     )
     login_url: str = Field(
         ...,
-        description='Path of the login URL (do not include the base URL)',
-        examples=['session'],
-        title='Login Path',
+        description="Path of the login URL (do not include the base URL)",
+        examples=["session"],
+        title="Login Path",
     )
     session_token: Optional[str] = Field(
         None,
-        description='Session token to use if using a pre-defined token. Not needed if authenticating with username + password pair',
+        description="Session token to use if using a pre-defined token. Not needed if authenticating with username + password pair",
         example=["{{ config['session_token'] }}"],
-        title='Session Token',
+        title="Session Token",
     )
     session_token_response_key: str = Field(
         ...,
-        description='Name of the key of the session token to be extracted from the response',
-        examples=['id'],
-        title='Response Token Response Key',
+        description="Name of the key of the session token to be extracted from the response",
+        examples=["id"],
+        title="Response Token Response Key",
     )
     username: Optional[str] = Field(
         None,
-        description='Username used to authenticate and obtain a session token',
+        description="Username used to authenticate and obtain a session token",
         examples=[" {{ config['username'] }}"],
-        title='Username',
+        title="Username",
     )
     password: Optional[str] = Field(
-        '',
-        description='Password used to authenticate and obtain a session token',
-        examples=["{{ config['password'] }}", ''],
-        title='Password',
+        "",
+        description="Password used to authenticate and obtain a session token",
+        examples=["{{ config['password'] }}", ""],
+        title="Password",
     )
     validate_session_url: str = Field(
         ...,
-        description='Path of the URL to use to validate that the session token is valid (do not include the base URL)',
-        examples=['user/current'],
-        title='Validate Session Path',
+        description="Path of the URL to use to validate that the session token is valid (do not include the base URL)",
+        examples=["user/current"],
+        title="Validate Session Path",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class ValueType(Enum):
-    string = 'string'
-    number = 'number'
-    integer = 'integer'
-    boolean = 'boolean'
+    string = "string"
+    number = "number"
+    integer = "integer"
+    boolean = "boolean"
 
 
 class WaitTimeFromHeader(BaseModel):
-    type: Literal['WaitTimeFromHeader']
+    type: Literal["WaitTimeFromHeader"]
     header: str = Field(
         ...,
-        description='The name of the response header defining how long to wait before retrying.',
-        examples=['Retry-After'],
-        title='Response Header Name',
+        description="The name of the response header defining how long to wait before retrying.",
+        examples=["Retry-After"],
+        title="Response Header Name",
     )
     regex: Optional[str] = Field(
         None,
-        description='Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.',
-        examples=['([-+]?\\d+)'],
-        title='Extraction Regex',
+        description="Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.",
+        examples=["([-+]?\\d+)"],
+        title="Extraction Regex",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class WaitUntilTimeFromHeader(BaseModel):
-    type: Literal['WaitUntilTimeFromHeader']
+    type: Literal["WaitUntilTimeFromHeader"]
     header: str = Field(
         ...,
-        description='The name of the response header defining how long to wait before retrying.',
-        examples=['wait_time'],
-        title='Response Header',
+        description="The name of the response header defining how long to wait before retrying.",
+        examples=["wait_time"],
+        title="Response Header",
     )
     min_wait: Optional[Union[float, str]] = Field(
         None,
-        description='Minimum time to wait before retrying.',
-        examples=[10, '60'],
-        title='Minimum Wait Time',
+        description="Minimum time to wait before retrying.",
+        examples=[10, "60"],
+        title="Minimum Wait Time",
     )
     regex: Optional[str] = Field(
         None,
-        description='Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.',
-        examples=['([-+]?\\d+)'],
-        title='Extraction Regex',
+        description="Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.",
+        examples=["([-+]?\\d+)"],
+        title="Extraction Regex",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class AddedFieldDefinition(BaseModel):
-    type: Literal['AddedFieldDefinition']
+    type: Literal["AddedFieldDefinition"]
     path: List[str] = Field(
         ...,
-        description='List of strings defining the path where to add the value on the record.',
-        examples=[['segment_id'], ['metadata', 'segment_id']],
-        title='Path',
+        description="List of strings defining the path where to add the value on the record.",
+        examples=[["segment_id"], ["metadata", "segment_id"]],
+        title="Path",
     )
     value: str = Field(
         ...,
@@ -741,187 +735,185 @@ class AddedFieldDefinition(BaseModel):
             "{{ record['MetaData']['LastUpdatedTime'] }}",
             "{{ stream_partition['segment_id'] }}",
         ],
-        title='Value',
+        title="Value",
     )
     value_type: Optional[ValueType] = Field(
         None,
-        description='Type of the value. If not specified, the type will be inferred from the value.',
-        title='Value Type',
+        description="Type of the value. If not specified, the type will be inferred from the value.",
+        title="Value Type",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class AddFields(BaseModel):
-    type: Literal['AddFields']
+    type: Literal["AddFields"]
     fields: List[AddedFieldDefinition] = Field(
         ...,
-        description='List of transformations (path and corresponding value) that will be added to the record.',
-        title='Fields',
+        description="List of transformations (path and corresponding value) that will be added to the record.",
+        title="Fields",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class ApiKeyAuthenticator(BaseModel):
-    type: Literal['ApiKeyAuthenticator']
+    type: Literal["ApiKeyAuthenticator"]
     api_token: Optional[str] = Field(
         None,
-        description='The API key to inject in the request. Fill it in the user inputs.',
+        description="The API key to inject in the request. Fill it in the user inputs.",
         examples=["{{ config['api_key'] }}", "Token token={{ config['api_key'] }}"],
-        title='API Key',
+        title="API Key",
     )
     header: Optional[str] = Field(
         None,
-        description='The name of the HTTP header that will be set to the API key. This setting is deprecated, use inject_into instead. Header and inject_into can not be defined at the same time.',
-        examples=['Authorization', 'Api-Token', 'X-Auth-Token'],
-        title='Header Name',
+        description="The name of the HTTP header that will be set to the API key. This setting is deprecated, use inject_into instead. Header and inject_into can not be defined at the same time.",
+        examples=["Authorization", "Api-Token", "X-Auth-Token"],
+        title="Header Name",
     )
     inject_into: Optional[RequestOption] = Field(
         None,
-        description='Configure how the API Key will be sent in requests to the source API. Either inject_into or header has to be defined.',
+        description="Configure how the API Key will be sent in requests to the source API. Either inject_into or header has to be defined.",
         examples=[
-            {'inject_into': 'header', 'field_name': 'Authorization'},
-            {'inject_into': 'request_parameter', 'field_name': 'authKey'},
+            {"inject_into": "header", "field_name": "Authorization"},
+            {"inject_into": "request_parameter", "field_name": "authKey"},
         ],
-        title='Inject API Key Into Outgoing HTTP Request',
+        title="Inject API Key Into Outgoing HTTP Request",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class AuthFlow(BaseModel):
-    auth_flow_type: Optional[AuthFlowType] = Field(
-        None, description='The type of auth to use', title='Auth flow type'
-    )
+    auth_flow_type: Optional[AuthFlowType] = Field(None, description="The type of auth to use", title="Auth flow type")
     predicate_key: Optional[List[str]] = Field(
         None,
-        description='JSON path to a field in the connectorSpecification that should exist for the advanced auth to be applicable.',
-        examples=[['credentials', 'auth_type']],
-        title='Predicate key',
+        description="JSON path to a field in the connectorSpecification that should exist for the advanced auth to be applicable.",
+        examples=[["credentials", "auth_type"]],
+        title="Predicate key",
     )
     predicate_value: Optional[str] = Field(
         None,
-        description='Value of the predicate_key fields for the advanced auth to be applicable.',
-        examples=['Oauth'],
-        title='Predicate value',
+        description="Value of the predicate_key fields for the advanced auth to be applicable.",
+        examples=["Oauth"],
+        title="Predicate value",
     )
     oauth_config_specification: Optional[OAuthConfigSpecification] = None
 
 
 class CursorPagination(BaseModel):
-    type: Literal['CursorPagination']
+    type: Literal["CursorPagination"]
     cursor_value: str = Field(
         ...,
-        description='Value of the cursor defining the next page to fetch.',
+        description="Value of the cursor defining the next page to fetch.",
         examples=[
-            '{{ headers.link.next.cursor }}',
+            "{{ headers.link.next.cursor }}",
             "{{ last_records[-1]['key'] }}",
             "{{ response['nextPage'] }}",
         ],
-        title='Cursor Value',
+        title="Cursor Value",
     )
     page_size: Optional[int] = Field(
         None,
-        description='The number of records to include in each pages.',
+        description="The number of records to include in each pages.",
         examples=[100],
-        title='Page Size',
+        title="Page Size",
     )
     stop_condition: Optional[str] = Field(
         None,
-        description='Template string evaluating when to stop paginating.',
+        description="Template string evaluating when to stop paginating.",
         examples=[
-            '{{ response.data.has_more is false }}',
+            "{{ response.data.has_more is false }}",
             "{{ 'next' not in headers['link'] }}",
         ],
-        title='Stop Condition',
+        title="Stop Condition",
     )
     decoder: Optional[JsonDecoder] = Field(
         None,
-        description='Component decoding the response so records can be extracted.',
-        title='Decoder',
+        description="Component decoding the response so records can be extracted.",
+        title="Decoder",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DatetimeBasedCursor(BaseModel):
-    type: Literal['DatetimeBasedCursor']
+    type: Literal["DatetimeBasedCursor"]
     cursor_field: str = Field(
         ...,
-        description='The location of the value on a record that will be used as a bookmark during sync. To ensure no data loss, the API must return records in ascending order based on the cursor field. Nested fields are not supported, so the field must be at the top level of the record. You can use a combination of Add Field and Remove Field transformations to move the nested field to the top.',
-        examples=['created_at', "{{ config['record_cursor'] }}"],
-        title='Cursor Field',
+        description="The location of the value on a record that will be used as a bookmark during sync. To ensure no data loss, the API must return records in ascending order based on the cursor field. Nested fields are not supported, so the field must be at the top level of the record. You can use a combination of Add Field and Remove Field transformations to move the nested field to the top.",
+        examples=["created_at", "{{ config['record_cursor'] }}"],
+        title="Cursor Field",
     )
     datetime_format: str = Field(
         ...,
-        description='The datetime format used to format the datetime values that are sent in outgoing requests to the API. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:\n  * **%s**: Epoch unix timestamp - `1686218963`\n  * **%ms**: Epoch unix timestamp (milliseconds) - `1686218963123`\n  * **%a**: Weekday (abbreviated) - `Sun`\n  * **%A**: Weekday (full) - `Sunday`\n  * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n  * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n  * **%b**: Month (abbreviated) - `Jan`\n  * **%B**: Month (full) - `January`\n  * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n  * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n  * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n  * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n  * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n  * **%p**: AM/PM indicator\n  * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n  * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n  * **%f**: Microsecond (zero-padded to 6 digits) - `000000`\n  * **%z**: UTC offset - `(empty)`, `+0000`, `-04:00`\n  * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n  * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n  * **%U**: Week number of the year (starting Sunday) - `00`, ..., `53`\n  * **%W**: Week number of the year (starting Monday) - `00`, ..., `53`\n  * **%c**: Date and time - `Tue Aug 16 21:30:00 1988`\n  * **%x**: Date standard format - `08/16/1988`\n  * **%X**: Time standard format - `21:30:00`\n  * **%%**: Literal \'%\' character\n\n  Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n',
-        examples=['%Y-%m-%dT%H:%M:%S.%f%z', '%Y-%m-%d', '%s', '%ms'],
-        title='Outgoing Datetime Format',
+        description="The datetime format used to format the datetime values that are sent in outgoing requests to the API. Use placeholders starting with \"%\" to describe the format the API is using. The following placeholders are available:\n  * **%s**: Epoch unix timestamp - `1686218963`\n  * **%ms**: Epoch unix timestamp (milliseconds) - `1686218963123`\n  * **%a**: Weekday (abbreviated) - `Sun`\n  * **%A**: Weekday (full) - `Sunday`\n  * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n  * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n  * **%b**: Month (abbreviated) - `Jan`\n  * **%B**: Month (full) - `January`\n  * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n  * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n  * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n  * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n  * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n  * **%p**: AM/PM indicator\n  * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n  * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n  * **%f**: Microsecond (zero-padded to 6 digits) - `000000`\n  * **%z**: UTC offset - `(empty)`, `+0000`, `-04:00`\n  * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n  * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n  * **%U**: Week number of the year (starting Sunday) - `00`, ..., `53`\n  * **%W**: Week number of the year (starting Monday) - `00`, ..., `53`\n  * **%c**: Date and time - `Tue Aug 16 21:30:00 1988`\n  * **%x**: Date standard format - `08/16/1988`\n  * **%X**: Time standard format - `21:30:00`\n  * **%%**: Literal '%' character\n\n  Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n",
+        examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s", "%ms"],
+        title="Outgoing Datetime Format",
     )
     start_datetime: Union[str, MinMaxDatetime] = Field(
         ...,
-        description='The datetime that determines the earliest record that should be synced.',
-        examples=['2020-01-1T00:00:00Z', "{{ config['start_time'] }}"],
-        title='Start Datetime',
+        description="The datetime that determines the earliest record that should be synced.",
+        examples=["2020-01-1T00:00:00Z", "{{ config['start_time'] }}"],
+        title="Start Datetime",
     )
     cursor_datetime_formats: Optional[List[str]] = Field(
         None,
-        description='The possible formats for the cursor field, in order of preference. The first format that matches the cursor field value will be used to parse it. If not provided, the `datetime_format` will be used.',
-        title='Cursor Datetime Formats',
+        description="The possible formats for the cursor field, in order of preference. The first format that matches the cursor field value will be used to parse it. If not provided, the `datetime_format` will be used.",
+        title="Cursor Datetime Formats",
     )
     cursor_granularity: Optional[str] = Field(
         None,
-        description='Smallest increment the datetime_format has (ISO 8601 duration) that is used to ensure the start of a slice does not overlap with the end of the previous one, e.g. for %Y-%m-%d the granularity should be P1D, for %Y-%m-%dT%H:%M:%SZ the granularity should be PT1S. Given this field is provided, `step` needs to be provided as well.',
-        examples=['PT1S'],
-        title='Cursor Granularity',
+        description="Smallest increment the datetime_format has (ISO 8601 duration) that is used to ensure the start of a slice does not overlap with the end of the previous one, e.g. for %Y-%m-%d the granularity should be P1D, for %Y-%m-%dT%H:%M:%SZ the granularity should be PT1S. Given this field is provided, `step` needs to be provided as well.",
+        examples=["PT1S"],
+        title="Cursor Granularity",
     )
     end_datetime: Optional[Union[str, MinMaxDatetime]] = Field(
         None,
-        description='The datetime that determines the last record that should be synced. If not provided, `{{ now_utc() }}` will be used.',
-        examples=['2021-01-1T00:00:00Z', '{{ now_utc() }}', '{{ day_delta(-1) }}'],
-        title='End Datetime',
+        description="The datetime that determines the last record that should be synced. If not provided, `{{ now_utc() }}` will be used.",
+        examples=["2021-01-1T00:00:00Z", "{{ now_utc() }}", "{{ day_delta(-1) }}"],
+        title="End Datetime",
     )
     end_time_option: Optional[RequestOption] = Field(
         None,
-        description='Optionally configures how the end datetime will be sent in requests to the source API.',
-        title='Inject End Time Into Outgoing HTTP Request',
+        description="Optionally configures how the end datetime will be sent in requests to the source API.",
+        title="Inject End Time Into Outgoing HTTP Request",
     )
     is_data_feed: Optional[bool] = Field(
         None,
-        description='A data feed API is an API that does not allow filtering and paginates the content from the most recent to the least recent. Given this, the CDK needs to know when to stop paginating and this field will generate a stop condition for pagination.',
-        title='Whether the target API is formatted as a data feed',
+        description="A data feed API is an API that does not allow filtering and paginates the content from the most recent to the least recent. Given this, the CDK needs to know when to stop paginating and this field will generate a stop condition for pagination.",
+        title="Whether the target API is formatted as a data feed",
     )
     lookback_window: Optional[str] = Field(
         None,
-        description='Time interval before the start_datetime to read data for, e.g. P1M for looking back one month.',
-        examples=['P1D', "P{{ config['lookback_days'] }}D"],
-        title='Lookback Window',
+        description="Time interval before the start_datetime to read data for, e.g. P1M for looking back one month.",
+        examples=["P1D", "P{{ config['lookback_days'] }}D"],
+        title="Lookback Window",
     )
     partition_field_end: Optional[str] = Field(
         None,
-        description='Name of the partition start time field.',
-        examples=['ending_time'],
-        title='Partition Field End',
+        description="Name of the partition start time field.",
+        examples=["ending_time"],
+        title="Partition Field End",
     )
     partition_field_start: Optional[str] = Field(
         None,
-        description='Name of the partition end time field.',
-        examples=['starting_time'],
-        title='Partition Field Start',
+        description="Name of the partition end time field.",
+        examples=["starting_time"],
+        title="Partition Field Start",
     )
     start_time_option: Optional[RequestOption] = Field(
         None,
-        description='Optionally configures how the start datetime will be sent in requests to the source API.',
-        title='Inject Start Time Into Outgoing HTTP Request',
+        description="Optionally configures how the start datetime will be sent in requests to the source API.",
+        title="Inject Start Time Into Outgoing HTTP Request",
     )
     step: Optional[str] = Field(
         None,
-        description='The size of the time window (ISO8601 duration). Given this field is provided, `cursor_granularity` needs to be provided as well.',
-        examples=['P1W', "{{ config['step_increment'] }}"],
-        title='Step',
+        description="The size of the time window (ISO8601 duration). Given this field is provided, `cursor_granularity` needs to be provided as well.",
+        examples=["P1W", "{{ config['step_increment'] }}"],
+        title="Step",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DefaultErrorHandler(BaseModel):
-    type: Literal['DefaultErrorHandler']
+    type: Literal["DefaultErrorHandler"]
     backoff_strategies: Optional[
         List[
             Union[
@@ -934,145 +926,143 @@ class DefaultErrorHandler(BaseModel):
         ]
     ] = Field(
         None,
-        description='List of backoff strategies to use to determine how long to wait before retrying a retryable request.',
-        title='Backoff Strategies',
+        description="List of backoff strategies to use to determine how long to wait before retrying a retryable request.",
+        title="Backoff Strategies",
     )
     max_retries: Optional[int] = Field(
         5,
-        description='The maximum number of time to retry a retryable request before giving up and failing.',
+        description="The maximum number of time to retry a retryable request before giving up and failing.",
         examples=[5, 0, 10],
-        title='Max Retry Count',
+        title="Max Retry Count",
     )
     response_filters: Optional[List[HttpResponseFilter]] = Field(
         None,
         description="List of response filters to iterate on when deciding how to handle an error. When using an array of multiple filters, the filters will be applied sequentially and the response will be selected if it matches any of the filter's predicate.",
-        title='Response Filters',
+        title="Response Filters",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DefaultPaginator(BaseModel):
-    type: Literal['DefaultPaginator']
-    pagination_strategy: Union[
-        CursorPagination, CustomPaginationStrategy, OffsetIncrement, PageIncrement
-    ] = Field(
+    type: Literal["DefaultPaginator"]
+    pagination_strategy: Union[CursorPagination, CustomPaginationStrategy, OffsetIncrement, PageIncrement] = Field(
         ...,
-        description='Strategy defining how records are paginated.',
-        title='Pagination Strategy',
+        description="Strategy defining how records are paginated.",
+        title="Pagination Strategy",
     )
     decoder: Optional[JsonDecoder] = Field(
         None,
-        description='Component decoding the response so records can be extracted.',
-        title='Decoder',
+        description="Component decoding the response so records can be extracted.",
+        title="Decoder",
     )
     page_size_option: Optional[RequestOption] = None
     page_token_option: Optional[Union[RequestOption, RequestPath]] = None
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DpathExtractor(BaseModel):
-    type: Literal['DpathExtractor']
+    type: Literal["DpathExtractor"]
     field_path: List[str] = Field(
         ...,
         description='List of potentially nested fields describing the full path of the field to extract. Use "*" to extract all values from an array. See more info in the [docs](https://docs.airbyte.com/connector-development/config-based/understanding-the-yaml-file/record-selector).',
         examples=[
-            ['data'],
-            ['data', 'records'],
-            ['data', '{{ parameters.name }}'],
-            ['data', '*', 'record'],
+            ["data"],
+            ["data", "records"],
+            ["data", "{{ parameters.name }}"],
+            ["data", "*", "record"],
         ],
-        title='Field Path',
+        title="Field Path",
     )
     decoder: Optional[JsonDecoder] = Field(
         None,
-        description='Component decoding the response so records can be extracted.',
-        title='Decoder',
+        description="Component decoding the response so records can be extracted.",
+        title="Decoder",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SessionTokenRequestApiKeyAuthenticator(BaseModel):
-    type: Literal['ApiKey']
+    type: Literal["ApiKey"]
     inject_into: RequestOption = Field(
         ...,
-        description='Configure how the API Key will be sent in requests to the source API.',
+        description="Configure how the API Key will be sent in requests to the source API.",
         examples=[
-            {'inject_into': 'header', 'field_name': 'Authorization'},
-            {'inject_into': 'request_parameter', 'field_name': 'authKey'},
+            {"inject_into": "header", "field_name": "Authorization"},
+            {"inject_into": "request_parameter", "field_name": "authKey"},
         ],
-        title='Inject API Key Into Outgoing HTTP Request',
+        title="Inject API Key Into Outgoing HTTP Request",
     )
 
 
 class ListPartitionRouter(BaseModel):
-    type: Literal['ListPartitionRouter']
+    type: Literal["ListPartitionRouter"]
     cursor_field: str = Field(
         ...,
         description='While iterating over list values, the name of field used to reference a list value. The partition value can be accessed with string interpolation. e.g. "{{ stream_partition[\'my_key\'] }}" where "my_key" is the value of the cursor_field.',
-        examples=['section', "{{ config['section_key'] }}"],
-        title='Current Partition Value Identifier',
+        examples=["section", "{{ config['section_key'] }}"],
+        title="Current Partition Value Identifier",
     )
     values: Union[str, List[str]] = Field(
         ...,
-        description='The list of attributes being iterated over and used as input for the requests made to the source API.',
-        examples=[['section_a', 'section_b', 'section_c'], "{{ config['sections'] }}"],
-        title='Partition Values',
+        description="The list of attributes being iterated over and used as input for the requests made to the source API.",
+        examples=[["section_a", "section_b", "section_c"], "{{ config['sections'] }}"],
+        title="Partition Values",
     )
     request_option: Optional[RequestOption] = Field(
         None,
-        description='A request option describing where the list value should be injected into and under what field name if applicable.',
-        title='Inject Partition Value Into Outgoing HTTP Request',
+        description="A request option describing where the list value should be injected into and under what field name if applicable.",
+        title="Inject Partition Value Into Outgoing HTTP Request",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class RecordSelector(BaseModel):
-    type: Literal['RecordSelector']
+    type: Literal["RecordSelector"]
     extractor: Union[CustomRecordExtractor, DpathExtractor]
     record_filter: Optional[RecordFilter] = Field(
         None,
-        description='Responsible for filtering records to be emitted by the Source.',
-        title='Record Filter',
+        description="Responsible for filtering records to be emitted by the Source.",
+        title="Record Filter",
     )
     schema_normalization: Optional[SchemaNormalization] = SchemaNormalization.None_
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class Spec(BaseModel):
-    type: Literal['Spec']
+    type: Literal["Spec"]
     connection_specification: Dict[str, Any] = Field(
         ...,
-        description='A connection specification describing how a the connector can be configured.',
-        title='Connection Specification',
+        description="A connection specification describing how a the connector can be configured.",
+        title="Connection Specification",
     )
     documentation_url: Optional[str] = Field(
         None,
         description="URL of the connector's documentation page.",
-        examples=['https://docs.airbyte.com/integrations/sources/dremio'],
-        title='Documentation URL',
+        examples=["https://docs.airbyte.com/integrations/sources/dremio"],
+        title="Documentation URL",
     )
     advanced_auth: Optional[AuthFlow] = Field(
         None,
-        description='Advanced specification for configuring the authentication flow.',
-        title='Advanced Auth',
+        description="Advanced specification for configuring the authentication flow.",
+        title="Advanced Auth",
     )
 
 
 class CompositeErrorHandler(BaseModel):
-    type: Literal['CompositeErrorHandler']
+    type: Literal["CompositeErrorHandler"]
     error_handlers: List[Union[CompositeErrorHandler, DefaultErrorHandler]] = Field(
         ...,
-        description='List of error handlers to iterate on to determine how to handle a failed response.',
-        title='Error Handlers',
+        description="List of error handlers to iterate on to determine how to handle a failed response.",
+        title="Error Handlers",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DeclarativeSource(BaseModel):
     class Config:
         extra = Extra.forbid
 
-    type: Literal['DeclarativeSource']
+    type: Literal["DeclarativeSource"]
     check: CheckStream
     streams: List[DeclarativeStream]
     version: str
@@ -1081,7 +1071,7 @@ class Config:
     spec: Optional[Spec] = None
     metadata: Optional[Dict[str, Any]] = Field(
         None,
-        description='For internal Airbyte use only - DO NOT modify manually. Used by consumers of declarative manifests for storing related metadata.',
+        description="For internal Airbyte use only - DO NOT modify manually. Used by consumers of declarative manifests for storing related metadata.",
     )
 
 
@@ -1089,12 +1079,12 @@ class SelectiveAuthenticator(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['SelectiveAuthenticator']
+    type: Literal["SelectiveAuthenticator"]
     authenticator_selection_path: List[str] = Field(
         ...,
-        description='Path of the field in config with selected authenticator name',
-        examples=[['auth'], ['auth', 'type']],
-        title='Authenticator Selection Path',
+        description="Path of the field in config with selected authenticator name",
+        examples=[["auth"], ["auth", "type"]],
+        title="Authenticator Selection Path",
     )
     authenticators: Dict[
         str,
@@ -1110,119 +1100,109 @@ class Config:
         ],
     ] = Field(
         ...,
-        description='Authenticators to select from.',
+        description="Authenticators to select from.",
         examples=[
             {
-                'authenticators': {
-                    'token': '#/definitions/ApiKeyAuthenticator',
-                    'oauth': '#/definitions/OAuthAuthenticator',
+                "authenticators": {
+                    "token": "#/definitions/ApiKeyAuthenticator",
+                    "oauth": "#/definitions/OAuthAuthenticator",
                 }
             }
         ],
-        title='Authenticators',
+        title="Authenticators",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class DeclarativeStream(BaseModel):
     class Config:
         extra = Extra.allow
 
-    type: Literal['DeclarativeStream']
+    type: Literal["DeclarativeStream"]
     retriever: Union[CustomRetriever, SimpleRetriever] = Field(
         ...,
-        description='Component used to coordinate how records are extracted across stream slices and request pages.',
-        title='Retriever',
+        description="Component used to coordinate how records are extracted across stream slices and request pages.",
+        title="Retriever",
     )
-    incremental_sync: Optional[
-        Union[CustomIncrementalSync, DatetimeBasedCursor]
-    ] = Field(
+    incremental_sync: Optional[Union[CustomIncrementalSync, DatetimeBasedCursor]] = Field(
         None,
-        description='Component used to fetch data incrementally based on a time field in the data.',
-        title='Incremental Sync',
-    )
-    name: Optional[str] = Field(
-        '', description='The stream name.', example=['Users'], title='Name'
-    )
-    primary_key: Optional[PrimaryKey] = Field(
-        '', description='The primary key of the stream.', title='Primary Key'
+        description="Component used to fetch data incrementally based on a time field in the data.",
+        title="Incremental Sync",
     )
+    name: Optional[str] = Field("", description="The stream name.", example=["Users"], title="Name")
+    primary_key: Optional[PrimaryKey] = Field("", description="The primary key of the stream.", title="Primary Key")
     schema_loader: Optional[Union[InlineSchemaLoader, JsonFileSchemaLoader]] = Field(
         None,
-        description='Component used to retrieve the schema for the current stream.',
-        title='Schema Loader',
+        description="Component used to retrieve the schema for the current stream.",
+        title="Schema Loader",
     )
-    transformations: Optional[
-        List[Union[AddFields, CustomTransformation, RemoveFields]]
-    ] = Field(
+    transformations: Optional[List[Union[AddFields, CustomTransformation, RemoveFields]]] = Field(
         None,
-        description='A list of transformations to be applied to each output record.',
-        title='Transformations',
+        description="A list of transformations to be applied to each output record.",
+        title="Transformations",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SessionTokenAuthenticator(BaseModel):
-    type: Literal['SessionTokenAuthenticator']
+    type: Literal["SessionTokenAuthenticator"]
     login_requester: HttpRequester = Field(
         ...,
-        description='Description of the request to perform to obtain a session token to perform data requests. The response body is expected to be a JSON object with a session token property.',
+        description="Description of the request to perform to obtain a session token to perform data requests. The response body is expected to be a JSON object with a session token property.",
         examples=[
             {
-                'type': 'HttpRequester',
-                'url_base': 'https://my_api.com',
-                'path': '/login',
-                'authenticator': {
-                    'type': 'BasicHttpAuthenticator',
-                    'username': '{{ config.username }}',
-                    'password': '{{ config.password }}',
+                "type": "HttpRequester",
+                "url_base": "https://my_api.com",
+                "path": "/login",
+                "authenticator": {
+                    "type": "BasicHttpAuthenticator",
+                    "username": "{{ config.username }}",
+                    "password": "{{ config.password }}",
                 },
             }
         ],
-        title='Login Requester',
+        title="Login Requester",
     )
     session_token_path: List[str] = Field(
         ...,
-        description='The path in the response body returned from the login requester to the session token.',
-        examples=[['access_token'], ['result', 'token']],
-        title='Session Token Path',
+        description="The path in the response body returned from the login requester to the session token.",
+        examples=[["access_token"], ["result", "token"]],
+        title="Session Token Path",
     )
     expiration_duration: Optional[str] = Field(
         None,
-        description='The duration in ISO 8601 duration notation after which the session token expires, starting from the time it was obtained. Omitting it will result in the session token being refreshed for every request.',
-        examples=['PT1H', 'P1D'],
-        title='Expiration Duration',
+        description="The duration in ISO 8601 duration notation after which the session token expires, starting from the time it was obtained. Omitting it will result in the session token being refreshed for every request.",
+        examples=["PT1H", "P1D"],
+        title="Expiration Duration",
     )
-    request_authentication: Union[
-        SessionTokenRequestApiKeyAuthenticator, SessionTokenRequestBearerAuthenticator
-    ] = Field(
+    request_authentication: Union[SessionTokenRequestApiKeyAuthenticator, SessionTokenRequestBearerAuthenticator] = Field(
         ...,
-        description='Authentication method to use for requests sent to the API, specifying how to inject the session token.',
-        title='Data Request Authentication',
+        description="Authentication method to use for requests sent to the API, specifying how to inject the session token.",
+        title="Data Request Authentication",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class HttpRequester(BaseModel):
-    type: Literal['HttpRequester']
+    type: Literal["HttpRequester"]
     url_base: str = Field(
         ...,
-        description='Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.',
+        description="Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
         examples=[
-            'https://connect.squareup.com/v2',
+            "https://connect.squareup.com/v2",
             "{{ config['base_url'] or 'https://app.posthog.com'}}/api/",
         ],
-        title='API Base URL',
+        title="API Base URL",
     )
     path: str = Field(
         ...,
-        description='Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.',
+        description="Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
         examples=[
-            '/products',
+            "/products",
             "/quotes/{{ stream_partition['id'] }}/quote_line_groups",
             "/trades/{{ config['symbol_id'] }}/history",
         ],
-        title='URL Path',
+        title="URL Path",
     )
     authenticator: Optional[
         Union[
@@ -1238,101 +1218,97 @@ class HttpRequester(BaseModel):
         ]
     ] = Field(
         None,
-        description='Authentication method to use for requests sent to the API.',
-        title='Authenticator',
+        description="Authentication method to use for requests sent to the API.",
+        title="Authenticator",
     )
-    error_handler: Optional[
-        Union[DefaultErrorHandler, CustomErrorHandler, CompositeErrorHandler]
-    ] = Field(
+    error_handler: Optional[Union[DefaultErrorHandler, CustomErrorHandler, CompositeErrorHandler]] = Field(
         None,
-        description='Error handler component that defines how to handle errors.',
-        title='Error Handler',
+        description="Error handler component that defines how to handle errors.",
+        title="Error Handler",
     )
     http_method: Optional[HttpMethod] = Field(
         HttpMethod.GET,
-        description='The HTTP method used to fetch data from the source (can be GET or POST).',
-        examples=['GET', 'POST'],
-        title='HTTP Method',
+        description="The HTTP method used to fetch data from the source (can be GET or POST).",
+        examples=["GET", "POST"],
+        title="HTTP Method",
     )
     request_body_data: Optional[Union[str, Dict[str, str]]] = Field(
         None,
-        description='Specifies how to populate the body of the request with a non-JSON payload. Plain text will be sent as is, whereas objects will be converted to a urlencoded form.',
+        description="Specifies how to populate the body of the request with a non-JSON payload. Plain text will be sent as is, whereas objects will be converted to a urlencoded form.",
         examples=[
             '[{"clause": {"type": "timestamp", "operator": 10, "parameters":\n    [{"value": {{ stream_interval[\'start_time\'] | int * 1000 }} }]\n  }, "orderBy": 1, "columnName": "Timestamp"}]/\n'
         ],
-        title='Request Body Payload (Non-JSON)',
+        title="Request Body Payload (Non-JSON)",
     )
     request_body_json: Optional[Union[str, Dict[str, Any]]] = Field(
         None,
-        description='Specifies how to populate the body of the request with a JSON payload. Can contain nested objects.',
+        description="Specifies how to populate the body of the request with a JSON payload. Can contain nested objects.",
         examples=[
-            {'sort_order': 'ASC', 'sort_field': 'CREATED_AT'},
-            {'key': "{{ config['value'] }}"},
-            {'sort': {'field': 'updated_at', 'order': 'ascending'}},
+            {"sort_order": "ASC", "sort_field": "CREATED_AT"},
+            {"key": "{{ config['value'] }}"},
+            {"sort": {"field": "updated_at", "order": "ascending"}},
         ],
-        title='Request Body JSON Payload',
+        title="Request Body JSON Payload",
     )
     request_headers: Optional[Union[str, Dict[str, str]]] = Field(
         None,
-        description='Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.',
-        examples=[{'Output-Format': 'JSON'}, {'Version': "{{ config['version'] }}"}],
-        title='Request Headers',
+        description="Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.",
+        examples=[{"Output-Format": "JSON"}, {"Version": "{{ config['version'] }}"}],
+        title="Request Headers",
     )
     request_parameters: Optional[Union[str, Dict[str, str]]] = Field(
         None,
-        description='Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.',
+        description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
         examples=[
-            {'unit': 'day'},
+            {"unit": "day"},
             {
-                'query': 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
+                "query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
             },
-            {'searchIn': "{{ ','.join(config.get('search_in', [])) }}"},
-            {'sort_by[asc]': 'updated_at'},
+            {"searchIn": "{{ ','.join(config.get('search_in', [])) }}"},
+            {"sort_by[asc]": "updated_at"},
         ],
-        title='Query Parameters',
+        title="Query Parameters",
     )
     use_cache: Optional[bool] = Field(
         False,
-        description='Enables stream requests caching. This field is automatically set by the CDK.',
-        title='Use Cache',
+        description="Enables stream requests caching. This field is automatically set by the CDK.",
+        title="Use Cache",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class ParentStreamConfig(BaseModel):
-    type: Literal['ParentStreamConfig']
+    type: Literal["ParentStreamConfig"]
     parent_key: str = Field(
         ...,
-        description='The primary key of records from the parent stream that will be used during the retrieval of records for the current substream. This parent identifier field is typically a characteristic of the child records being extracted from the source API.',
-        examples=['id', "{{ config['parent_record_id'] }}"],
-        title='Parent Key',
-    )
-    stream: DeclarativeStream = Field(
-        ..., description='Reference to the parent stream.', title='Parent Stream'
+        description="The primary key of records from the parent stream that will be used during the retrieval of records for the current substream. This parent identifier field is typically a characteristic of the child records being extracted from the source API.",
+        examples=["id", "{{ config['parent_record_id'] }}"],
+        title="Parent Key",
     )
+    stream: DeclarativeStream = Field(..., description="Reference to the parent stream.", title="Parent Stream")
     partition_field: str = Field(
         ...,
-        description='While iterating over parent records during a sync, the parent_key value can be referenced by using this field.',
-        examples=['parent_id', "{{ config['parent_partition_field'] }}"],
-        title='Current Parent Key Value Identifier',
+        description="While iterating over parent records during a sync, the parent_key value can be referenced by using this field.",
+        examples=["parent_id", "{{ config['parent_partition_field'] }}"],
+        title="Current Parent Key Value Identifier",
     )
     request_option: Optional[RequestOption] = Field(
         None,
-        description='A request option describing where the parent key value should be injected into and under what field name if applicable.',
-        title='Request Option',
+        description="A request option describing where the parent key value should be injected into and under what field name if applicable.",
+        title="Request Option",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SimpleRetriever(BaseModel):
-    type: Literal['SimpleRetriever']
+    type: Literal["SimpleRetriever"]
     record_selector: RecordSelector = Field(
         ...,
-        description='Component that describes how to extract records from a HTTP response.',
+        description="Component that describes how to extract records from a HTTP response.",
     )
     requester: Union[CustomRequester, HttpRequester] = Field(
         ...,
-        description='Requester component that describes how to prepare HTTP requests to send to the source API.',
+        description="Requester component that describes how to prepare HTTP requests to send to the source API.",
     )
     paginator: Optional[Union[DefaultPaginator, NoPagination]] = Field(
         None,
@@ -1347,28 +1323,24 @@ class SimpleRetriever(BaseModel):
             CustomPartitionRouter,
             ListPartitionRouter,
             SubstreamPartitionRouter,
-            List[
-                Union[
-                    CustomPartitionRouter, ListPartitionRouter, SubstreamPartitionRouter
-                ]
-            ],
+            List[Union[CustomPartitionRouter, ListPartitionRouter, SubstreamPartitionRouter]],
         ]
     ] = Field(
         [],
-        description='PartitionRouter component that describes how to partition the stream, enabling incremental syncs and checkpointing.',
-        title='Partition Router',
+        description="PartitionRouter component that describes how to partition the stream, enabling incremental syncs and checkpointing.",
+        title="Partition Router",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 class SubstreamPartitionRouter(BaseModel):
-    type: Literal['SubstreamPartitionRouter']
+    type: Literal["SubstreamPartitionRouter"]
     parent_stream_configs: List[ParentStreamConfig] = Field(
         ...,
-        description='Specifies which parent streams are being iterated over and how parent records should be used to partition the child stream data set.',
-        title='Parent Stream Configs',
+        description="Specifies which parent streams are being iterated over and how parent records should be used to partition the child stream data set.",
+        title="Parent Stream Configs",
     )
-    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+    parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
 CompositeErrorHandler.update_forward_refs()
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py
index 9841bbd51dba..5413709d9615 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py
@@ -81,7 +81,7 @@ def _get_request_option(self, request_option_type: RequestOptionType, stream_sli
         if self.request_option and self.request_option.inject_into == request_option_type and stream_slice:
             slice_value = stream_slice.get(self.cursor_field.eval(self.config))
             if slice_value:
-                return {self.request_option.field_name: slice_value}
+                return {self.request_option.field_name.eval(self.config): slice_value}
             else:
                 return {}
         else:
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py
index c080e56a49ce..3e915168c059 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py
@@ -100,7 +100,7 @@ def _get_request_option(self, option_type: RequestOptionType, stream_slice: Stre
                     key = parent_config.partition_field.eval(self.config)
                     value = stream_slice.get(key)
                     if value:
-                        params.update({parent_config.request_option.field_name: value})
+                        params.update({parent_config.request_option.field_name.eval(config=self.config): value})
         return params
 
     def stream_slices(self) -> Iterable[StreamSlice]:
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py
index e23b948859fc..824efe9aed39 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py
@@ -164,9 +164,9 @@ def _get_request_options(self, option_type: RequestOptionType) -> MutableMapping
             and isinstance(self.page_token_option, RequestOption)
             and self.page_token_option.inject_into == option_type
         ):
-            options[self.page_token_option.field_name] = self._token
+            options[self.page_token_option.field_name.eval(config=self.config)] = self._token
         if self.page_size_option and self.pagination_strategy.get_page_size() and self.page_size_option.inject_into == option_type:
-            options[self.page_size_option.field_name] = self.pagination_strategy.get_page_size()
+            options[self.page_size_option.field_name.eval(config=self.config)] = self.pagination_strategy.get_page_size()
         return options
 
 
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/request_option.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/request_option.py
index 47de679c8944..d13d2056681d 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/request_option.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/requesters/request_option.py
@@ -4,7 +4,9 @@
 
 from dataclasses import InitVar, dataclass
 from enum import Enum
-from typing import Any, Mapping
+from typing import Any, Mapping, Union
+
+from airbyte_cdk.sources.declarative.interpolation.interpolated_string import InterpolatedString
 
 
 class RequestOptionType(Enum):
@@ -28,6 +30,9 @@ class RequestOption:
         inject_into (RequestOptionType): Describes where in the HTTP request to inject the parameter
     """
 
-    field_name: str
+    field_name: Union[InterpolatedString, str]
     inject_into: RequestOptionType
     parameters: InitVar[Mapping[str, Any]]
+
+    def __post_init__(self, parameters: Mapping[str, Any]) -> None:
+        self.field_name = InterpolatedString.create(self.field_name, parameters=parameters)
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/file_based/availability_strategy/__init__.py b/airbyte-cdk/python/airbyte_cdk/sources/file_based/availability_strategy/__init__.py
index 56204e9b74e6..a05e5421000a 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/file_based/availability_strategy/__init__.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/file_based/availability_strategy/__init__.py
@@ -1,7 +1,4 @@
-from .abstract_file_based_availability_strategy import (
-    AbstractFileBasedAvailabilityStrategy,
-    AbstractFileBasedAvailabilityStrategyWrapper,
-)
+from .abstract_file_based_availability_strategy import AbstractFileBasedAvailabilityStrategy, AbstractFileBasedAvailabilityStrategyWrapper
 from .default_file_based_availability_strategy import DefaultFileBasedAvailabilityStrategy
 
 __all__ = ["AbstractFileBasedAvailabilityStrategy", "AbstractFileBasedAvailabilityStrategyWrapper", "DefaultFileBasedAvailabilityStrategy"]
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py b/airbyte-cdk/python/airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py
index 646c595ebc37..6ab66bb39888 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py
@@ -1,5 +1,5 @@
 from .abstract_concurrent_file_based_cursor import AbstractConcurrentFileBasedCursor
-from .file_based_noop_cursor import FileBasedNoopCursor
 from .file_based_concurrent_cursor import FileBasedConcurrentCursor
+from .file_based_noop_cursor import FileBasedNoopCursor
 
 __all__ = ["AbstractConcurrentFileBasedCursor", "FileBasedConcurrentCursor", "FileBasedNoopCursor"]
diff --git a/airbyte-cdk/python/unit_tests/destinations/vector_db_based/document_processor_test.py b/airbyte-cdk/python/unit_tests/destinations/vector_db_based/document_processor_test.py
index 0e8760b73cc7..41da64916368 100644
--- a/airbyte-cdk/python/unit_tests/destinations/vector_db_based/document_processor_test.py
+++ b/airbyte-cdk/python/unit_tests/destinations/vector_db_based/document_processor_test.py
@@ -285,7 +285,7 @@ def test_process_multiple_chunks_with_relevant_fields():
                 "text: Special tokens like",
                 "<|endoftext|> are treated like regular",
                 "text",
-            ]
+            ],
         ),
         (
             "Custom separator",
diff --git a/airbyte-cdk/python/unit_tests/destinations/vector_db_based/embedder_test.py b/airbyte-cdk/python/unit_tests/destinations/vector_db_based/embedder_test.py
index 3cf8e4114e5b..a5f22b752ed2 100644
--- a/airbyte-cdk/python/unit_tests/destinations/vector_db_based/embedder_test.py
+++ b/airbyte-cdk/python/unit_tests/destinations/vector_db_based/embedder_test.py
@@ -118,8 +118,6 @@ def test_openai_chunking():
 
     mock_embedding_instance.embed_documents.side_effect = lambda texts: [[0] * OPEN_AI_VECTOR_SIZE] * len(texts)
 
-    chunks = [
-        Document(page_content="a", record=AirbyteRecordMessage(stream="mystream", data={}, emitted_at=0)) for _ in range(1005)
-    ]
+    chunks = [Document(page_content="a", record=AirbyteRecordMessage(stream="mystream", data={}, emitted_at=0)) for _ in range(1005)]
     assert embedder.embed_documents(chunks) == [[0] * OPEN_AI_VECTOR_SIZE] * 1005
     mock_embedding_instance.embed_documents.assert_has_calls([call(["a"] * 1000), call(["a"] * 5)])
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/auth/test_token_auth.py b/airbyte-cdk/python/unit_tests/sources/declarative/auth/test_token_auth.py
index 4db4a1ea0b0a..599667c42f9b 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/auth/test_token_auth.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/auth/test_token_auth.py
@@ -83,7 +83,7 @@ def test_api_key_authenticator(test_name, header, token, expected_header, expect
     """
     token_provider = InterpolatedStringTokenProvider(config=config, api_token=token, parameters=parameters)
     token_auth = ApiKeyAuthenticator(
-        request_option=RequestOption(inject_into=RequestOptionType.header, field_name=header, parameters={}),
+        request_option=RequestOption(inject_into=RequestOptionType.header, field_name=header, parameters=parameters),
         token_provider=token_provider,
         config=config,
         parameters=parameters,
@@ -192,7 +192,7 @@ def test_api_key_authenticator_inject(test_name, field_name, token, expected_fie
     """
     token_provider = InterpolatedStringTokenProvider(config=config, api_token=token, parameters=parameters)
     token_auth = ApiKeyAuthenticator(
-        request_option=RequestOption(inject_into=inject_type, field_name=field_name, parameters={}),
+        request_option=RequestOption(inject_into=inject_type, field_name=field_name, parameters=parameters),
         token_provider=token_provider,
         config=config,
         parameters=parameters,
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py b/airbyte-cdk/python/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py
index 08cea962086e..c96c19850578 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py
@@ -232,7 +232,7 @@ def test_full_config_stream():
 
     assert isinstance(stream.retriever.paginator, DefaultPaginator)
     assert isinstance(stream.retriever.paginator.decoder, JsonDecoder)
-    assert stream.retriever.paginator.page_size_option.field_name == "page_size"
+    assert stream.retriever.paginator.page_size_option.field_name.eval(input_config) == "page_size"
     assert stream.retriever.paginator.page_size_option.inject_into == RequestOptionType.request_parameter
     assert isinstance(stream.retriever.paginator.page_token_option, RequestPath)
     assert stream.retriever.paginator.url_base.string == "https://api.sendgrid.com/v3/"
@@ -422,7 +422,7 @@ def test_list_based_stream_slicer_with_values_defined_in_config():
     assert isinstance(partition_router, ListPartitionRouter)
     assert partition_router.values == ["airbyte", "airbyte-cloud"]
     assert partition_router.request_option.inject_into == RequestOptionType.header
-    assert partition_router.request_option.field_name == "repository"
+    assert partition_router.request_option.field_name.eval(config=input_config) == "repository"
 
 
 def test_create_substream_partition_router():
@@ -484,7 +484,7 @@ def test_create_substream_partition_router():
     assert partition_router.parent_stream_configs[0].parent_key.eval({}) == "id"
     assert partition_router.parent_stream_configs[0].partition_field.eval({}) == "repository_id"
     assert partition_router.parent_stream_configs[0].request_option.inject_into == RequestOptionType.request_parameter
-    assert partition_router.parent_stream_configs[0].request_option.field_name == "repository_id"
+    assert partition_router.parent_stream_configs[0].request_option.field_name.eval(config=input_config) == "repository_id"
 
     assert partition_router.parent_stream_configs[1].parent_key.eval({}) == "someid"
     assert partition_router.parent_stream_configs[1].partition_field.eval({}) == "word_id"
@@ -509,17 +509,17 @@ def test_datetime_based_cursor():
         start_time_option:
           type: RequestOption
           inject_into: request_parameter
-          field_name: created[gte]
+          field_name: "since_{{ config['cursor_field'] }}"
         end_time_option:
           type: RequestOption
           inject_into: body_json
-          field_name: end_time
+          field_name: "before_{{ parameters['cursor_field'] }}"
         partition_field_start: star
         partition_field_end: en
     """
     parsed_manifest = YamlDeclarativeSource._parse(content)
     resolved_manifest = resolver.preprocess_manifest(parsed_manifest)
-    slicer_manifest = transformer.propagate_types_and_parameters("", resolved_manifest["incremental"], {})
+    slicer_manifest = transformer.propagate_types_and_parameters("", resolved_manifest["incremental"], {"cursor_field": "created_at"})
 
     stream_slicer = factory.create_component(model_type=DatetimeBasedCursorModel, component_definition=slicer_manifest, config=input_config)
 
@@ -529,9 +529,9 @@ def test_datetime_based_cursor():
     assert stream_slicer.cursor_granularity == "PT0.000001S"
     assert stream_slicer.lookback_window.string == "P5D"
     assert stream_slicer.start_time_option.inject_into == RequestOptionType.request_parameter
-    assert stream_slicer.start_time_option.field_name == "created[gte]"
+    assert stream_slicer.start_time_option.field_name.eval(config=input_config | {"cursor_field": "updated_at"}) == "since_updated_at"
     assert stream_slicer.end_time_option.inject_into == RequestOptionType.body_json
-    assert stream_slicer.end_time_option.field_name == "end_time"
+    assert stream_slicer.end_time_option.field_name.eval({}) == "before_created_at"
     assert stream_slicer.partition_field_start.eval({}) == "star"
     assert stream_slicer.partition_field_end.eval({}) == "en"
 
@@ -937,18 +937,20 @@ def test_create_request_with_session_authenticator():
     }
 
 
-@pytest.mark.parametrize("input_config, expected_authenticator_class", [
-    pytest.param(
-        {"auth": {"type": "token"}, "credentials": {"api_key": "some_key"}},
-        ApiKeyAuthenticator,
-        id="test_create_requester_with_selective_authenticator_and_token_selected",
-    ),
-    pytest.param(
-        {"auth": {"type": "oauth"}, "credentials": {"client_id": "ABC"}},
-        DeclarativeOauth2Authenticator,
-        id="test_create_requester_with_selective_authenticator_and_oauth_selected",
-    ),
-]
+@pytest.mark.parametrize(
+    "input_config, expected_authenticator_class",
+    [
+        pytest.param(
+            {"auth": {"type": "token"}, "credentials": {"api_key": "some_key"}},
+            ApiKeyAuthenticator,
+            id="test_create_requester_with_selective_authenticator_and_token_selected",
+        ),
+        pytest.param(
+            {"auth": {"type": "oauth"}, "credentials": {"client_id": "ABC"}},
+            DeclarativeOauth2Authenticator,
+            id="test_create_requester_with_selective_authenticator_and_oauth_selected",
+        ),
+    ],
 )
 def test_create_requester_with_selective_authenticator(input_config, expected_authenticator_class):
     content = """
@@ -1121,7 +1123,7 @@ def test_create_default_paginator():
 
     assert isinstance(paginator.page_size_option, RequestOption)
     assert paginator.page_size_option.inject_into == RequestOptionType.request_parameter
-    assert paginator.page_size_option.field_name == "page_size"
+    assert paginator.page_size_option.field_name.eval(config=input_config) == "page_size"
 
     assert isinstance(paginator.page_token_option, RequestPath)
 
@@ -1294,7 +1296,7 @@ def test_custom_components_do_not_contain_extra_fields():
     assert custom_substream_partition_router.parent_stream_configs[0].parent_key.eval({}) == "id"
     assert custom_substream_partition_router.parent_stream_configs[0].partition_field.eval({}) == "repository_id"
     assert custom_substream_partition_router.parent_stream_configs[0].request_option.inject_into == RequestOptionType.request_parameter
-    assert custom_substream_partition_router.parent_stream_configs[0].request_option.field_name == "repository_id"
+    assert custom_substream_partition_router.parent_stream_configs[0].request_option.field_name.eval(config=input_config) == "repository_id"
 
     assert isinstance(custom_substream_partition_router.custom_pagination_strategy, PageIncrement)
     assert custom_substream_partition_router.custom_pagination_strategy.page_size == 100
@@ -1343,7 +1345,7 @@ def test_parse_custom_component_fields_if_subcomponent():
     assert custom_substream_partition_router.parent_stream_configs[0].parent_key.eval({}) == "id"
     assert custom_substream_partition_router.parent_stream_configs[0].partition_field.eval({}) == "repository_id"
     assert custom_substream_partition_router.parent_stream_configs[0].request_option.inject_into == RequestOptionType.request_parameter
-    assert custom_substream_partition_router.parent_stream_configs[0].request_option.field_name == "repository_id"
+    assert custom_substream_partition_router.parent_stream_configs[0].request_option.field_name.eval(config=input_config) == "repository_id"
 
     assert isinstance(custom_substream_partition_router.custom_pagination_strategy, PageIncrement)
     assert custom_substream_partition_router.custom_pagination_strategy.page_size == 100
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py b/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py
index ce1b93b9d75b..3a83af1eb714 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py
@@ -12,39 +12,40 @@
 
 
 @pytest.mark.parametrize(
-    "test_name, partition_values, cursor_field, expected_slices",
+    "partition_values, cursor_field, expected_slices",
     [
         (
-            "test_single_element",
             ["customer", "store", "subscription"],
             "owner_resource",
             [{"owner_resource": "customer"}, {"owner_resource": "store"}, {"owner_resource": "subscription"}],
         ),
         (
-            "test_input_list_is_string",
             '["customer", "store", "subscription"]',
             "owner_resource",
             [{"owner_resource": "customer"}, {"owner_resource": "store"}, {"owner_resource": "subscription"}],
         ),
         (
-            "test_using_cursor_from_parameters",
             '["customer", "store", "subscription"]',
             "{{ parameters['cursor_field'] }}",
             [{"owner_resource": "customer"}, {"owner_resource": "store"}, {"owner_resource": "subscription"}],
         ),
     ],
+    ids=[
+        "test_single_element",
+        "test_input_list_is_string",
+        "test_using_cursor_from_parameters",
+    ],
 )
-def test_list_partition_router(test_name, partition_values, cursor_field, expected_slices):
+def test_list_partition_router(partition_values, cursor_field, expected_slices):
     slicer = ListPartitionRouter(values=partition_values, cursor_field=cursor_field, config={}, parameters=parameters)
     slices = [s for s in slicer.stream_slices()]
     assert slices == expected_slices
 
 
 @pytest.mark.parametrize(
-    "test_name, request_option, expected_req_params, expected_headers, expected_body_json, expected_body_data",
+    "request_option, expected_req_params, expected_headers, expected_body_json, expected_body_data",
     [
         (
-            "test_inject_into_req_param",
             RequestOption(inject_into=RequestOptionType.request_parameter, parameters={}, field_name="owner_resource"),
             {"owner_resource": "customer"},
             {},
@@ -52,7 +53,6 @@ def test_list_partition_router(test_name, partition_values, cursor_field, expect
             {},
         ),
         (
-            "test_pass_by_header",
             RequestOption(inject_into=RequestOptionType.header, parameters={}, field_name="owner_resource"),
             {},
             {"owner_resource": "customer"},
@@ -60,7 +60,6 @@ def test_list_partition_router(test_name, partition_values, cursor_field, expect
             {},
         ),
         (
-            "test_inject_into_body_json",
             RequestOption(inject_into=RequestOptionType.body_json, parameters={}, field_name="owner_resource"),
             {},
             {},
@@ -68,7 +67,6 @@ def test_list_partition_router(test_name, partition_values, cursor_field, expect
             {},
         ),
         (
-            "test_inject_into_body_data",
             RequestOption(inject_into=RequestOptionType.body_data, parameters={}, field_name="owner_resource"),
             {},
             {},
@@ -76,8 +74,14 @@ def test_list_partition_router(test_name, partition_values, cursor_field, expect
             {"owner_resource": "customer"},
         ),
     ],
+    ids=[
+        "test_inject_into_req_param",
+        "test_pass_by_header",
+        "test_inject_into_body_json",
+        "test_inject_into_body_data",
+    ],
 )
-def test_request_option(test_name, request_option, expected_req_params, expected_headers, expected_body_json, expected_body_data):
+def test_request_option(request_option, expected_req_params, expected_headers, expected_body_json, expected_body_data):
     partition_router = ListPartitionRouter(
         values=partition_values, cursor_field=cursor_field, config={}, request_option=request_option, parameters={}
     )
@@ -89,6 +93,31 @@ def test_request_option(test_name, request_option, expected_req_params, expected
     assert expected_body_data == partition_router.get_request_body_data(stream_slice=stream_slice)
 
 
+@pytest.mark.parametrize(
+    "field_name_interpolation, expected_request_params",
+    [
+        ("{{parameters['partition_name']}}", {"parameters_partition": "customer"}),
+        ("{{config['partition_name']}}", {"config_partition": "customer"}),
+    ],
+    ids=[
+        "parameters_interpolation",
+        "config_interpolation",
+    ],
+)
+def test_request_options_interpolation(field_name_interpolation: str, expected_request_params: dict):
+    config = {"partition_name": "config_partition"}
+    parameters = {"partition_name": "parameters_partition"}
+    request_option = RequestOption(
+        inject_into=RequestOptionType.request_parameter, parameters=parameters, field_name=field_name_interpolation
+    )
+    partition_router = ListPartitionRouter(
+        values=partition_values, cursor_field=cursor_field, config=config, request_option=request_option, parameters=parameters
+    )
+    stream_slice = {cursor_field: "customer"}
+
+    assert expected_request_params == partition_router.get_request_params(stream_slice=stream_slice)
+
+
 def test_request_option_before_updating_cursor():
     request_option = RequestOption(inject_into=RequestOptionType.request_parameter, parameters={}, field_name="owner_resource")
     partition_router = ListPartitionRouter(
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py b/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py
index e677666f46eb..618a0fdb23e9 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py
@@ -57,11 +57,10 @@ def read_records(
 
 
 @pytest.mark.parametrize(
-    "test_name, parent_stream_configs, expected_slices",
+    "parent_stream_configs, expected_slices",
     [
-        ("test_no_parents", [], None),
+        ([], None),
         (
-            "test_single_parent_slices_no_records",
             [
                 ParentStreamConfig(
                     stream=MockStream([{}], [], "first_stream"),
@@ -74,7 +73,6 @@ def read_records(
             [],
         ),
         (
-            "test_single_parent_slices_with_records",
             [
                 ParentStreamConfig(
                     stream=MockStream([{}], parent_records, "first_stream"),
@@ -87,7 +85,6 @@ def read_records(
             [{"first_stream_id": 1, "parent_slice": {}}, {"first_stream_id": 2, "parent_slice": {}}],
         ),
         (
-            "test_with_parent_slices_and_records",
             [
                 ParentStreamConfig(
                     stream=MockStream(parent_slices, all_parent_data, "first_stream"),
@@ -104,7 +101,6 @@ def read_records(
             ],
         ),
         (
-            "test_multiple_parent_streams",
             [
                 ParentStreamConfig(
                     stream=MockStream(parent_slices, data_first_parent_slice + data_second_parent_slice, "first_stream"),
@@ -130,7 +126,6 @@ def read_records(
             ],
         ),
         (
-            "test_missed_parent_key",
             [
                 ParentStreamConfig(
                     stream=MockStream([{}], [{"id": 0}, {"id": 1}, {"_id": 2}, {"id": 3}], "first_stream"),
@@ -147,7 +142,6 @@ def read_records(
             ],
         ),
         (
-            "test_dpath_extraction",
             [
                 ParentStreamConfig(
                     stream=MockStream([{}], [{"a": {"b": 0}}, {"a": {"b": 1}}, {"a": {"c": 2}}, {"a": {"b": 3}}], "first_stream"),
@@ -164,8 +158,17 @@ def read_records(
             ],
         ),
     ],
+    ids=[
+        "test_no_parents",
+        "test_single_parent_slices_no_records",
+        "test_single_parent_slices_with_records",
+        "test_with_parent_slices_and_records",
+        "test_multiple_parent_streams",
+        "test_missed_parent_key",
+        "test_dpath_extraction",
+    ],
 )
-def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
+def test_substream_slicer(parent_stream_configs, expected_slices):
     if expected_slices is None:
         try:
             SubstreamPartitionRouter(parent_stream_configs=parent_stream_configs, parameters={}, config={})
@@ -178,10 +181,9 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
 
 
 @pytest.mark.parametrize(
-    "test_name, parent_stream_request_parameters, expected_req_params, expected_headers, expected_body_json, expected_body_data",
+    "parent_stream_request_parameters, expected_req_params, expected_headers, expected_body_json, expected_body_data",
     [
         (
-            "test_request_option_in_request_param",
             [
                 RequestOption(inject_into=RequestOptionType.request_parameter, parameters={}, field_name="first_stream"),
                 RequestOption(inject_into=RequestOptionType.request_parameter, parameters={}, field_name="second_stream"),
@@ -192,7 +194,6 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
             {},
         ),
         (
-            "test_request_option_in_header",
             [
                 RequestOption(inject_into=RequestOptionType.header, parameters={}, field_name="first_stream"),
                 RequestOption(inject_into=RequestOptionType.header, parameters={}, field_name="second_stream"),
@@ -203,7 +204,6 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
             {},
         ),
         (
-            "test_request_option_in_param_and_header",
             [
                 RequestOption(inject_into=RequestOptionType.request_parameter, parameters={}, field_name="first_stream"),
                 RequestOption(inject_into=RequestOptionType.header, parameters={}, field_name="second_stream"),
@@ -214,7 +214,6 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
             {},
         ),
         (
-            "test_request_option_in_body_json",
             [
                 RequestOption(inject_into=RequestOptionType.body_json, parameters={}, field_name="first_stream"),
                 RequestOption(inject_into=RequestOptionType.body_json, parameters={}, field_name="second_stream"),
@@ -225,7 +224,6 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
             {},
         ),
         (
-            "test_request_option_in_body_data",
             [
                 RequestOption(inject_into=RequestOptionType.body_data, parameters={}, field_name="first_stream"),
                 RequestOption(inject_into=RequestOptionType.body_data, parameters={}, field_name="second_stream"),
@@ -236,9 +234,15 @@ def test_substream_slicer(test_name, parent_stream_configs, expected_slices):
             {"first_stream": "1234", "second_stream": "4567"},
         ),
     ],
+    ids=[
+        "test_request_option_in_request_param",
+        "test_request_option_in_header",
+        "test_request_option_in_param_and_header",
+        "test_request_option_in_body_json",
+        "test_request_option_in_body_data",
+    ],
 )
 def test_request_option(
-    test_name,
     parent_stream_request_parameters,
     expected_req_params,
     expected_headers,
@@ -275,6 +279,61 @@ def test_request_option(
     assert expected_body_data == partition_router.get_request_body_data(stream_slice=stream_slice)
 
 
+@pytest.mark.parametrize(
+    "field_name_first_stream, field_name_second_stream, expected_request_params",
+    [
+        (
+            "{{parameters['field_name_first_stream']}}",
+            "{{parameters['field_name_second_stream']}}",
+            {"parameter_first_stream_id": "1234", "parameter_second_stream_id": "4567"},
+        ),
+        (
+            "{{config['field_name_first_stream']}}",
+            "{{config['field_name_second_stream']}}",
+            {"config_first_stream_id": "1234", "config_second_stream_id": "4567"},
+        ),
+    ],
+    ids=[
+        "parameters_interpolation",
+        "config_interpolation",
+    ],
+)
+def test_request_params_interpolation_for_parent_stream(
+    field_name_first_stream: str, field_name_second_stream: str, expected_request_params: dict
+):
+    config = {"field_name_first_stream": "config_first_stream_id", "field_name_second_stream": "config_second_stream_id"}
+    parameters = {"field_name_first_stream": "parameter_first_stream_id", "field_name_second_stream": "parameter_second_stream_id"}
+    partition_router = SubstreamPartitionRouter(
+        parent_stream_configs=[
+            ParentStreamConfig(
+                stream=MockStream(parent_slices, data_first_parent_slice + data_second_parent_slice, "first_stream"),
+                parent_key="id",
+                partition_field="first_stream_id",
+                parameters=parameters,
+                config=config,
+                request_option=RequestOption(
+                    inject_into=RequestOptionType.request_parameter, parameters=parameters, field_name=field_name_first_stream
+                ),
+            ),
+            ParentStreamConfig(
+                stream=MockStream(second_parent_stream_slice, more_records, "second_stream"),
+                parent_key="id",
+                partition_field="second_stream_id",
+                parameters=parameters,
+                config=config,
+                request_option=RequestOption(
+                    inject_into=RequestOptionType.request_parameter, parameters=parameters, field_name=field_name_second_stream
+                ),
+            ),
+        ],
+        parameters=parameters,
+        config=config,
+    )
+    stream_slice = {"first_stream_id": "1234", "second_stream_id": "4567"}
+
+    assert expected_request_params == partition_router.get_request_params(stream_slice=stream_slice)
+
+
 def test_given_record_is_airbyte_message_when_stream_slices_then_use_record_data():
     parent_slice = {}
     partition_router = SubstreamPartitionRouter(
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py b/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py
index 17ef223171c3..d8326d5227ec 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py
@@ -21,10 +21,9 @@
 
 
 @pytest.mark.parametrize(
-    "test_name, page_token_request_option, stop_condition, expected_updated_path, expected_request_params, expected_headers, expected_body_data, expected_body_json, last_records, expected_next_page_token, limit",
+    "page_token_request_option, stop_condition, expected_updated_path, expected_request_params, expected_headers, expected_body_data, expected_body_json, last_records, expected_next_page_token, limit",
     [
         (
-            "test_default_paginator_path",
             RequestPath(parameters={}),
             None,
             "/next_url",
@@ -37,7 +36,6 @@
             2,
         ),
         (
-            "test_default_paginator_request_param",
             RequestOption(inject_into=RequestOptionType.request_parameter, field_name="from", parameters={}),
             None,
             None,
@@ -50,7 +48,6 @@
             2,
         ),
         (
-            "test_default_paginator_no_token",
             RequestOption(inject_into=RequestOptionType.request_parameter, field_name="from", parameters={}),
             InterpolatedBoolean(condition="{{True}}", parameters={}),
             None,
@@ -63,7 +60,6 @@
             2,
         ),
         (
-            "test_default_paginator_cursor_header",
             RequestOption(inject_into=RequestOptionType.header, field_name="from", parameters={}),
             None,
             None,
@@ -76,7 +72,6 @@
             2,
         ),
         (
-            "test_default_paginator_cursor_body_data",
             RequestOption(inject_into=RequestOptionType.body_data, field_name="from", parameters={}),
             None,
             None,
@@ -89,7 +84,6 @@
             2,
         ),
         (
-            "test_default_paginator_cursor_body_json",
             RequestOption(inject_into=RequestOptionType.body_json, field_name="from", parameters={}),
             None,
             None,
@@ -102,9 +96,16 @@
             2,
         ),
     ],
+    ids=[
+        "test_default_paginator_path",
+        "test_default_paginator_request_param",
+        "test_default_paginator_no_token",
+        "test_default_paginator_cursor_header",
+        "test_default_paginator_cursor_body_data",
+        "test_default_paginator_cursor_body_json",
+    ],
 )
 def test_default_paginator_with_cursor(
-    test_name,
     page_token_request_option,
     stop_condition,
     expected_updated_path,
@@ -116,7 +117,9 @@ def test_default_paginator_with_cursor(
     expected_next_page_token,
     limit,
 ):
-    page_size_request_option = RequestOption(inject_into=RequestOptionType.request_parameter, field_name="limit", parameters={})
+    page_size_request_option = RequestOption(
+        inject_into=RequestOptionType.request_parameter, field_name="{{parameters['page_limit']}}", parameters={"page_limit": "limit"}
+    )
     cursor_value = "{{ response.next }}"
     url_base = "https://airbyte.io"
     config = {}
@@ -157,6 +160,62 @@ def test_default_paginator_with_cursor(
     assert actual_body_json == expected_body_json
 
 
+@pytest.mark.parametrize(
+    "field_name_page_size_interpolation, field_name_page_token_interpolation, expected_request_params",
+    [
+        (
+            "{{parameters['page_limit']}}",
+            "{{parameters['page_token']}}",
+            {"parameters_limit": 50, "parameters_token": "https://airbyte.io/next_url"},
+        ),
+        ("{{config['page_limit']}}", "{{config['page_token']}}", {"config_limit": 50, "config_token": "https://airbyte.io/next_url"}),
+    ],
+    ids=[
+        "parameters_interpolation",
+        "config_interpolation",
+    ],
+)
+def test_paginator_request_param_interpolation(
+    field_name_page_size_interpolation: str, field_name_page_token_interpolation: str, expected_request_params: dict
+):
+    config = {"page_limit": "config_limit", "page_token": "config_token"}
+    parameters = {"page_limit": "parameters_limit", "page_token": "parameters_token"}
+    page_size_request_option = RequestOption(
+        inject_into=RequestOptionType.request_parameter,
+        field_name=field_name_page_size_interpolation,
+        parameters=parameters,
+    )
+    cursor_value = "{{ response.next }}"
+    url_base = "https://airbyte.io"
+    limit = 50
+    strategy = CursorPaginationStrategy(
+        page_size=limit,
+        cursor_value=cursor_value,
+        stop_condition=None,
+        decoder=JsonDecoder(parameters={}),
+        config=config,
+        parameters=parameters,
+    )
+    paginator = DefaultPaginator(
+        page_size_option=page_size_request_option,
+        page_token_option=RequestOption(
+            inject_into=RequestOptionType.request_parameter, field_name=field_name_page_token_interpolation, parameters=parameters
+        ),
+        pagination_strategy=strategy,
+        config=config,
+        url_base=url_base,
+        parameters=parameters,
+    )
+    response = requests.Response()
+    response.headers = {"A_HEADER": "HEADER_VALUE"}
+    response_body = {"next": "https://airbyte.io/next_url"}
+    response._content = json.dumps(response_body).encode("utf-8")
+    last_records = [{"id": 0}, {"id": 1}]
+    paginator.next_page_token(response, last_records)
+    actual_request_params = paginator.get_request_params()
+    assert actual_request_params == expected_request_params
+
+
 def test_page_size_option_cannot_be_set_if_strategy_has_no_limit():
     page_size_request_option = RequestOption(inject_into=RequestOptionType.request_parameter, field_name="page_size", parameters={})
     page_token_request_option = RequestOption(inject_into=RequestOptionType.request_parameter, field_name="offset", parameters={})
diff --git a/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_request_option.py b/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_request_option.py
index 1dc2b070fa65..5caa11f57f16 100644
--- a/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_request_option.py
+++ b/airbyte-cdk/python/unit_tests/sources/declarative/requesters/paginators/test_request_option.py
@@ -7,15 +7,37 @@
 
 
 @pytest.mark.parametrize(
-    "test_name, option_type, field_name",
+    "option_type, field_name, expected_field_name",
     [
-        ("test_limit_param_with_field_name", RequestOptionType.request_parameter, "field"),
-        ("test_limit_header_with_field_name", RequestOptionType.header, "field"),
-        ("test_limit_data_with_field_name", RequestOptionType.body_data, "field"),
-        ("test_limit_json_with_field_name", RequestOptionType.body_json, "field"),
+        (RequestOptionType.request_parameter, "field", "field"),
+        (RequestOptionType.header, "field", "field"),
+        (RequestOptionType.body_data, "field", "field"),
+        (RequestOptionType.body_json, "field", "field"),
+        (RequestOptionType.request_parameter, "since_{{ parameters['cursor_field'] }}", "since_updated_at"),
+        (RequestOptionType.header, "since_{{ parameters['cursor_field'] }}", "since_updated_at"),
+        (RequestOptionType.body_data, "since_{{ parameters['cursor_field'] }}", "since_updated_at"),
+        (RequestOptionType.body_json, "since_{{ parameters['cursor_field'] }}", "since_updated_at"),
+        (RequestOptionType.request_parameter, "since_{{ config['cursor_field'] }}", "since_created_at"),
+        (RequestOptionType.header, "since_{{ config['cursor_field'] }}", "since_created_at"),
+        (RequestOptionType.body_data, "since_{{ config['cursor_field'] }}", "since_created_at"),
+        (RequestOptionType.body_json, "since_{{ config['cursor_field'] }}", "since_created_at"),
+    ],
+    ids=[
+        "test_limit_param_with_field_name",
+        "test_limit_header_with_field_name",
+        "test_limit_data_with_field_name",
+        "test_limit_json_with_field_name",
+        "test_limit_param_with_parameters_interpolation",
+        "test_limit_header_with_parameters_interpolation",
+        "test_limit_data_with_parameters_interpolation",
+        "test_limit_json_with_parameters_interpolation",
+        "test_limit_param_with_config_interpolation",
+        "test_limit_header_with_config_interpolation",
+        "test_limit_data_with_config_interpolation",
+        "test_limit_json_with_config_interpolation",
     ],
 )
-def test_request_option(test_name, option_type, field_name):
-    request_option = RequestOption(inject_into=option_type, field_name=field_name, parameters={})
-    assert request_option.field_name == field_name
+def test_request_option(option_type: RequestOptionType, field_name: str, expected_field_name: str):
+    request_option = RequestOption(inject_into=option_type, field_name=field_name, parameters={"cursor_field": "updated_at"})
+    assert request_option.field_name.eval({"cursor_field": "created_at"}) == expected_field_name
     assert request_option.inject_into == option_type
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/file_types/test_unstructured_parser.py b/airbyte-cdk/python/unit_tests/sources/file_based/file_types/test_unstructured_parser.py
index 311d4a0ad158..9bc096c5136e 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/file_types/test_unstructured_parser.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/file_types/test_unstructured_parser.py
@@ -86,7 +86,10 @@ def test_infer_schema(mock_detect_filetype, filetype, format_config, raises):
         assert schema == {
             "content": {"type": "string", "description": "Content of the file as markdown. Might be null if the file could not be parsed"},
             "document_key": {"type": "string", "description": "Unique identifier of the document, e.g. the file path"},
-            "_ab_source_file_parse_error": {"type": "string", "description": "Error message if the file could not be parsed even though the file is supported"},
+            "_ab_source_file_parse_error": {
+                "type": "string",
+                "description": "Error message if the file could not be parsed even though the file is supported",
+            },
         }
     loop.close()
     asyncio.set_event_loop(main_loop)
@@ -201,7 +204,7 @@ def test_infer_schema(mock_detect_filetype, filetype, format_config, raises):
                 {
                     "content": None,
                     "document_key": FILE_URI,
-                    "_ab_source_file_parse_error": "Error parsing record. This could be due to a mismatch between the config's file type and the actual file type, or because the file or record is not parseable. Contact Support if you need assistance.\nfilename=path/to/file.xyz message=weird parsing error"
+                    "_ab_source_file_parse_error": "Error parsing record. This could be due to a mismatch between the config's file type and the actual file type, or because the file or record is not parseable. Contact Support if you need assistance.\nfilename=path/to/file.xyz message=weird parsing error",
                 }
             ],
             True,
@@ -323,33 +326,48 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             None,
             "test",
             [{"type": "Text", "text": "test"}],
-            [call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")})],
-            False,
             [
-                {
-                    "content": "test",
-                    "document_key": FILE_URI,
-                    "_ab_source_file_parse_error": None
-                }
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                )
             ],
+            False,
+            [{"content": "test", "document_key": FILE_URI, "_ab_source_file_parse_error": None}],
             200,
             id="basic_request",
         ),
         pytest.param(
             FileType.PDF,
-            UnstructuredFormat(skip_unprocessable_file_types=False, strategy="hi_res", processing=APIProcessingConfigModel(mode="api", api_key="test", api_url="http://localhost:8000", parameters=[APIParameterConfigModel(name="include_page_breaks", value="true"), APIParameterConfigModel(name="ocr_languages", value="eng"), APIParameterConfigModel(name="ocr_languages", value="kor")])),
+            UnstructuredFormat(
+                skip_unprocessable_file_types=False,
+                strategy="hi_res",
+                processing=APIProcessingConfigModel(
+                    mode="api",
+                    api_key="test",
+                    api_url="http://localhost:8000",
+                    parameters=[
+                        APIParameterConfigModel(name="include_page_breaks", value="true"),
+                        APIParameterConfigModel(name="ocr_languages", value="eng"),
+                        APIParameterConfigModel(name="ocr_languages", value="kor"),
+                    ],
+                ),
+            ),
             None,
             "test",
             [{"type": "Text", "text": "test"}],
-            [call("http://localhost:8000/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "hi_res", "include_page_breaks": "true", "ocr_languages": ["eng", "kor"]}, files={"files": ("filename", mock.ANY, "application/pdf")})],
-            False,
             [
-                {
-                    "content": "test",
-                    "document_key": FILE_URI,
-                    "_ab_source_file_parse_error": None
-                }
+                call(
+                    "http://localhost:8000/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "hi_res", "include_page_breaks": "true", "ocr_languages": ["eng", "kor"]},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                )
             ],
+            False,
+            [{"content": "test", "document_key": FILE_URI, "_ab_source_file_parse_error": None}],
             200,
             id="request_with_params",
         ),
@@ -361,13 +379,7 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             None,
             None,
             False,
-            [
-                {
-                    "content": "# Mymarkdown",
-                    "document_key": FILE_URI,
-                    "_ab_source_file_parse_error": None
-                }
-            ],
+            [{"content": "# Mymarkdown", "document_key": FILE_URI, "_ab_source_file_parse_error": None}],
             200,
             id="handle_markdown_locally",
         ),
@@ -384,15 +396,40 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             "test",
             None,
             [
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
             ],
             True,
@@ -411,21 +448,30 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             "test",
             [{"type": "Text", "text": "test"}],
             [
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
             ],
             False,
-            [
-                {
-                    "content": "test",
-                    "document_key": FILE_URI,
-                    "_ab_source_file_parse_error": None
-                }
-            ],
+            [{"content": "test", "document_key": FILE_URI, "_ab_source_file_parse_error": None}],
             200,
             id="retry_and_recover",
         ),
@@ -438,7 +484,12 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             "test",
             [{"type": "Text", "text": "test"}],
             [
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
             ],
             True,
@@ -455,7 +506,12 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             "test",
             [{"type": "Text", "text": "test"}],
             [
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
                 call().raise_for_status(),
             ],
             True,
@@ -470,7 +526,12 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
             "test",
             [{"detail": "Something went wrong"}],
             [
-                call("https://api.unstructured.io/general/v0/general", headers={"accept": "application/json", "unstructured-api-key": "test"}, data={"strategy": "auto"}, files={"files": ("filename", mock.ANY, "application/pdf")}),
+                call(
+                    "https://api.unstructured.io/general/v0/general",
+                    headers={"accept": "application/json", "unstructured-api-key": "test"},
+                    data={"strategy": "auto"},
+                    files={"files": ("filename", mock.ANY, "application/pdf")},
+                ),
             ],
             False,
             [
@@ -487,7 +548,7 @@ def test_check_config(requests_mock, format_config, raises_for_status, json_resp
 )
 @patch("airbyte_cdk.sources.file_based.file_types.unstructured_parser.requests")
 @patch("airbyte_cdk.sources.file_based.file_types.unstructured_parser.detect_filetype")
-@patch('time.sleep', side_effect=lambda _: None)
+@patch("time.sleep", side_effect=lambda _: None)
 def test_parse_records_remotely(
     time_mock,
     mock_detect_filetype,
@@ -500,7 +561,7 @@ def test_parse_records_remotely(
     expected_requests,
     raises,
     expected_records,
-    http_status_code
+    http_status_code,
 ):
     stream_reader = MagicMock()
     mock_open(stream_reader.open_file, read_data=bytes(str(file_content), "utf-8"))
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/concurrent_incremental_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/concurrent_incremental_scenarios.py
index 0629d683fec8..ccbcc1c7116a 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/concurrent_incremental_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/concurrent_incremental_scenarios.py
@@ -42,10 +42,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"some_old_file.csv": "2023-06-01T03:54:07.000000Z"},
-                "_ab_source_file_last_modified": "2023-06-01T03:54:07.000000Z_some_old_file.csv"
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"some_old_file.csv": "2023-06-01T03:54:07.000000Z"},
+                    "_ab_source_file_last_modified": "2023-06-01T03:54:07.000000Z_some_old_file.csv",
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -137,10 +142,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
-                "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_a.csv",
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
+                    "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_a.csv",
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -214,10 +224,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-01T03:54:07.000000Z"},
-                "_ab_source_file_last_modified": "2023-06-01T03:54:07.000000Z_a.csv",
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-01T03:54:07.000000Z"},
+                    "_ab_source_file_last_modified": "2023-06-01T03:54:07.000000Z_a.csv",
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -580,12 +595,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
-                "stream1", {
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
                     "history": {"recent_file.csv": "2023-07-15T23:59:59.000000Z"},
                     "_ab_source_file_last_modified": "2023-07-15T23:59:59.000000Z_recent_file.csv",
                 },
-            ).build(),
+            )
+            .build(),
         )
     )
 ).build()
@@ -1022,10 +1040,12 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
-                {"history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
-                 "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_a.csv"}).build(),
+                {"history": {"a.csv": "2023-06-05T03:54:07.000000Z"}, "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_a.csv"},
+            )
+            .build(),
         )
     )
 ).build()
@@ -1146,13 +1166,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {"a.csv": "2023-06-05T03:54:07.000000Z", "c.csv": "2023-06-06T03:54:07.000000Z"},
                     "_ab_source_file_last_modified": "2023-06-06T03:54:07.000000Z_c.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -1273,13 +1295,15 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {"a.csv": "2023-06-05T03:54:07.000000Z", "c.csv": "2023-06-06T03:54:07.000000Z"},
                     "_ab_source_file_last_modified": "2023-06-03T03:54:07.000000Z_x.csv",
-                }
-            ).build()
+                },
+            )
+            .build()
         )
     )
 ).build()
@@ -1454,7 +1478,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -1463,8 +1488,9 @@
                         "old_file_same_timestamp_as_a.csv": "2023-06-06T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-06T03:54:07.000000Z_old_file_same_timestamp_as_a.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -1639,7 +1665,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -1648,8 +1675,9 @@
                         "old_file_same_timestamp_as_a.csv": "2023-06-06T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-05-01T03:54:07.000000Z_very_very_very_old_file.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -2123,7 +2151,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2132,8 +2161,9 @@
                         "d.csv": "2023-06-05T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_b.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -2239,7 +2269,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2248,8 +2279,9 @@
                         "d.csv": "2023-06-05T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z_d.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -2378,7 +2410,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2387,8 +2420,9 @@
                         "e.csv": "2023-06-08T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-08T03:54:07.000000Z_e.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -2516,7 +2550,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2525,15 +2560,18 @@
                         "e.csv": "2023-06-08T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-08T03:54:07.000000Z_e.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
 
 multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_newer = (
     TestScenarioBuilder()
-    .set_name("multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_newer")
+    .set_name(
+        "multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_newer"
+    )
     .set_config(
         {
             "streams": [
@@ -2680,7 +2718,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2689,15 +2728,18 @@
                         "d.csv": "2023-06-08T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-08T03:54:07.000000Z_d.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
 
 multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_older = (
     TestScenarioBuilder()
-    .set_name("multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_older")
+    .set_name(
+        "multi_csv_sync_files_within_history_time_window_if_history_is_incomplete_different_timestamps_scenario_concurrent_cursor_is_older"
+    )
     .set_config(
         {
             "streams": [
@@ -2844,7 +2886,8 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state(
+            input_state=StateBuilder()
+            .with_stream_state(
                 "stream1",
                 {
                     "history": {
@@ -2853,8 +2896,9 @@
                         "d.csv": "2023-06-08T03:54:07.000000Z",
                     },
                     "_ab_source_file_last_modified": "2023-06-04T00:00:00.000000Z_very_old_file.csv",
-                }
-            ).build(),
+                },
+            )
+            .build(),
         )
     )
 ).build()
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/csv_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/csv_scenarios.py
index 0f3c0f0ef2a7..bba3977db2fd 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/csv_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/csv_scenarios.py
@@ -324,9 +324,7 @@
                                                 "processing": {
                                                     "title": "Processing",
                                                     "description": "Processing configuration",
-                                                    "default": {
-                                                        "mode": "local"
-                                                    },
+                                                    "default": {"mode": "local"},
                                                     "type": "object",
                                                     "oneOf": [
                                                         {
@@ -337,16 +335,12 @@
                                                                     "title": "Mode",
                                                                     "default": "local",
                                                                     "const": "local",
-                                                                    "enum": [
-                                                                        "local"
-                                                                    ],
-                                                                    "type": "string"
+                                                                    "enum": ["local"],
+                                                                    "type": "string",
                                                                 }
                                                             },
                                                             "description": "Process files locally, supporting `fast` and `ocr` modes. This is the default option.",
-                                                            "required": [
-                                                                "mode"
-                                                            ]
+                                                            "required": ["mode"],
                                                         },
                                                         {
                                                             "title": "via API",
@@ -356,10 +350,8 @@
                                                                     "title": "Mode",
                                                                     "default": "api",
                                                                     "const": "api",
-                                                                    "enum": [
-                                                                        "api"
-                                                                    ],
-                                                                    "type": "string"
+                                                                    "enum": ["api"],
+                                                                    "type": "string",
                                                                 },
                                                                 "api_key": {
                                                                     "title": "API Key",
@@ -367,17 +359,15 @@
                                                                     "default": "",
                                                                     "always_show": True,
                                                                     "airbyte_secret": True,
-                                                                    "type": "string"
+                                                                    "type": "string",
                                                                 },
                                                                 "api_url": {
                                                                     "title": "API URL",
                                                                     "description": "The URL of the unstructured API to use",
                                                                     "default": "https://api.unstructured.io",
                                                                     "always_show": True,
-                                                                    "examples": [
-                                                                        "https://api.unstructured.com"
-                                                                    ],
-                                                                    "type": "string"
+                                                                    "examples": ["https://api.unstructured.com"],
+                                                                    "type": "string",
                                                                 },
                                                                 "parameters": {
                                                                     "title": "Additional URL Parameters",
@@ -392,35 +382,24 @@
                                                                             "name": {
                                                                                 "title": "Parameter name",
                                                                                 "description": "The name of the unstructured API parameter to use",
-                                                                                "examples": [
-                                                                                    "combine_under_n_chars",
-                                                                                    "languages"
-                                                                                ],
-                                                                                "type": "string"
+                                                                                "examples": ["combine_under_n_chars", "languages"],
+                                                                                "type": "string",
                                                                             },
                                                                             "value": {
                                                                                 "title": "Value",
                                                                                 "description": "The value of the parameter",
-                                                                                "examples": [
-                                                                                    "true",
-                                                                                    "hi_res"
-                                                                                ],
-                                                                                "type": "string"
-                                                                            }
+                                                                                "examples": ["true", "hi_res"],
+                                                                                "type": "string",
+                                                                            },
                                                                         },
-                                                                        "required": [
-                                                                            "name",
-                                                                            "value"
-                                                                        ]
-                                                                    }
-                                                                }
+                                                                        "required": ["name", "value"],
+                                                                    },
+                                                                },
                                                             },
                                                             "description": "Process files via an API, using the `hi_res` mode. This option is useful for increased performance and accuracy, but requires an API key and a hosted instance of unstructured.",
-                                                            "required": [
-                                                                "mode"
-                                                            ]
-                                                        }
-                                                    ]
+                                                            "required": ["mode"],
+                                                        },
+                                                    ],
                                                 },
                                             },
                                             "description": "Extract text from document formats (.pdf, .docx, .md, .pptx) and emit as one record per file.",
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/incremental_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/incremental_scenarios.py
index 1b826d8766f7..3b9785e11bfe 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/incremental_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/incremental_scenarios.py
@@ -42,9 +42,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"some_old_file.csv": "2023-06-01T03:54:07.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"some_old_file.csv": "2023-06-01T03:54:07.000000Z"},
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -136,9 +141,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -212,9 +222,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-01T03:54:07.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-01T03:54:07.000000Z"},
+                },
+            )
+            .build(),
         )
     )
     .set_expected_records(
@@ -577,9 +592,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"recent_file.csv": "2023-07-15T23:59:59.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"recent_file.csv": "2023-07-15T23:59:59.000000Z"},
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -1016,9 +1036,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-05T03:54:07.000000Z"},
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -1139,9 +1164,14 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {"a.csv": "2023-06-05T03:54:07.000000Z", "c.csv": "2023-06-06T03:54:07.000000Z"},
-            }).build(),
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {"a.csv": "2023-06-05T03:54:07.000000Z", "c.csv": "2023-06-06T03:54:07.000000Z"},
+                },
+            )
+            .build(),
         )
     )
 ).build()
@@ -1316,13 +1346,18 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {
-                    "very_very_old_file.csv": "2023-06-01T03:54:07.000000Z",
-                    "very_old_file.csv": "2023-06-02T03:54:07.000000Z",
-                    "old_file_same_timestamp_as_a.csv": "2023-06-06T03:54:07.000000Z",
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {
+                        "very_very_old_file.csv": "2023-06-01T03:54:07.000000Z",
+                        "very_old_file.csv": "2023-06-02T03:54:07.000000Z",
+                        "old_file_same_timestamp_as_a.csv": "2023-06-06T03:54:07.000000Z",
+                    },
                 },
-            }).build(),
+            )
+            .build(),
         )
     )
 ).build()
@@ -1612,13 +1647,18 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {
-                    "b.csv": "2023-06-05T03:54:07.000000Z",
-                    "c.csv": "2023-06-05T03:54:07.000000Z",
-                    "d.csv": "2023-06-05T03:54:07.000000Z",
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {
+                        "b.csv": "2023-06-05T03:54:07.000000Z",
+                        "c.csv": "2023-06-05T03:54:07.000000Z",
+                        "d.csv": "2023-06-05T03:54:07.000000Z",
+                    },
                 },
-            }).build(),
+            )
+            .build(),
         )
     )
 ).build()
@@ -1746,13 +1786,18 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {
-                    "c.csv": "2023-06-07T03:54:07.000000Z",
-                    "d.csv": "2023-06-08T03:54:07.000000Z",
-                    "e.csv": "2023-06-08T03:54:07.000000Z",
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {
+                        "c.csv": "2023-06-07T03:54:07.000000Z",
+                        "d.csv": "2023-06-08T03:54:07.000000Z",
+                        "e.csv": "2023-06-08T03:54:07.000000Z",
+                    },
                 },
-            }).build(),
+            )
+            .build(),
         )
     )
 ).build()
@@ -1906,13 +1951,18 @@
     )
     .set_incremental_scenario_config(
         IncrementalScenarioConfig(
-            input_state=StateBuilder().with_stream_state("stream1", {
-                "history": {
-                    "old_file.csv": "2023-06-05T00:00:00.000000Z",
-                    "c.csv": "2023-06-07T03:54:07.000000Z",
-                    "d.csv": "2023-06-08T03:54:07.000000Z",
+            input_state=StateBuilder()
+            .with_stream_state(
+                "stream1",
+                {
+                    "history": {
+                        "old_file.csv": "2023-06-05T00:00:00.000000Z",
+                        "c.csv": "2023-06-07T03:54:07.000000Z",
+                        "d.csv": "2023-06-08T03:54:07.000000Z",
+                    },
                 },
-            }).build(),
+            )
+            .build(),
         )
     )
 ).build()
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/jsonl_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/jsonl_scenarios.py
index 2998f3deb6cc..cee4c5b9a1e2 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/jsonl_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/jsonl_scenarios.py
@@ -484,9 +484,7 @@
             ]
         }
     )
-    .set_expected_records(
-        []
-    )
+    .set_expected_records([])
     .set_expected_discover_error(AirbyteTracedException, FileBasedSourceError.SCHEMA_INFERENCE_ERROR.value)
     .set_expected_read_error(AirbyteTracedException, "Please check the logged errors for more information.")
     .set_expected_logs(
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/unstructured_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/unstructured_scenarios.py
index dc0824512a43..da1e468c9df5 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/unstructured_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/unstructured_scenarios.py
@@ -15,12 +15,18 @@
 json_schema = {
     "type": "object",
     "properties": {
-        "content": {"type": ["null", "string"], "description": "Content of the file as markdown. Might be null if the file could not be parsed"},
+        "content": {
+            "type": ["null", "string"],
+            "description": "Content of the file as markdown. Might be null if the file could not be parsed",
+        },
         "document_key": {"type": ["null", "string"], "description": "Unique identifier of the document, e.g. the file path"},
-        "_ab_source_file_parse_error": {"type": ["null", "string"], "description": "Error message if the file could not be parsed even though the file is supported"},
+        "_ab_source_file_parse_error": {
+            "type": ["null", "string"],
+            "description": "Error message if the file could not be parsed even though the file is supported",
+        },
         "_ab_source_file_last_modified": {"type": "string"},
         "_ab_source_file_url": {"type": "string"},
-    }
+    },
 }
 
 simple_markdown_scenario = (
@@ -69,7 +75,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -104,7 +110,6 @@
                     "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z",
                     "_ab_source_file_url": "c",
                     "_ab_source_file_parse_error": None,
-
                 },
                 "stream": "stream1",
             },
@@ -132,9 +137,7 @@
         .set_files(
             {
                 "a.txt": {
-                    "contents": bytes(
-                        "Just some raw text", "UTF-8"
-                    ),
+                    "contents": bytes("Just some raw text", "UTF-8"),
                     "last_modified": "2023-06-05T03:54:07.000Z",
                 },
                 "b": {
@@ -154,7 +157,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -179,7 +182,6 @@
                     "_ab_source_file_last_modified": "2023-06-05T03:54:07.000000Z",
                     "_ab_source_file_url": "b",
                     "_ab_source_file_parse_error": None,
-
                 },
                 "stream": "stream1",
             },
@@ -223,7 +225,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -273,7 +275,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -337,7 +339,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -417,7 +419,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -495,7 +497,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
@@ -563,7 +565,7 @@
                     "json_schema": json_schema,
                     "name": "stream1",
                     "source_defined_cursor": True,
-                    'source_defined_primary_key': [["document_key"]],
+                    "source_defined_primary_key": [["document_key"]],
                     "supported_sync_modes": ["full_refresh", "incremental"],
                 }
             ]
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/user_input_schema_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/user_input_schema_scenarios.py
index 58d528cb7caf..974bbf558974 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/user_input_schema_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/scenarios/user_input_schema_scenarios.py
@@ -442,7 +442,13 @@
             ]
         }
     )
-    .set_catalog(CatalogBuilder().with_stream("stream1", SyncMode.full_refresh).with_stream("stream2", SyncMode.full_refresh).with_stream("stream3", SyncMode.full_refresh).build())
+    .set_catalog(
+        CatalogBuilder()
+        .with_stream("stream1", SyncMode.full_refresh)
+        .with_stream("stream2", SyncMode.full_refresh)
+        .with_stream("stream3", SyncMode.full_refresh)
+        .build()
+    )
     .set_expected_check_status("FAILED")
     .set_expected_check_error(None, FileBasedSourceError.ERROR_PARSING_USER_PROVIDED_SCHEMA.value)
     .set_expected_discover_error(ConfigValidationError, FileBasedSourceError.ERROR_PARSING_USER_PROVIDED_SCHEMA.value)
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_adapters.py b/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_adapters.py
index e63f950b5b2a..2d93e73ced56 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_adapters.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_adapters.py
@@ -49,11 +49,15 @@
 def test_file_based_stream_partition_generator(sync_mode):
     stream = Mock()
     message_repository = Mock()
-    stream_slices = [{"files": [RemoteFile(uri="1", last_modified=datetime.now())]},
-                     {"files": [RemoteFile(uri="2", last_modified=datetime.now())]}]
+    stream_slices = [
+        {"files": [RemoteFile(uri="1", last_modified=datetime.now())]},
+        {"files": [RemoteFile(uri="2", last_modified=datetime.now())]},
+    ]
     stream.stream_slices.return_value = stream_slices
 
-    partition_generator = FileBasedStreamPartitionGenerator(stream, message_repository, _ANY_SYNC_MODE, _ANY_CURSOR_FIELD, _ANY_STATE, _ANY_CURSOR)
+    partition_generator = FileBasedStreamPartitionGenerator(
+        stream, message_repository, _ANY_SYNC_MODE, _ANY_CURSOR_FIELD, _ANY_STATE, _ANY_CURSOR
+    )
 
     partitions = list(partition_generator.generate())
     slices = [partition.to_slice() for partition in partitions]
@@ -134,7 +138,11 @@ def test_file_based_stream_partition_raising_exception(exception_type, expected_
 @pytest.mark.parametrize(
     "_slice, expected_hash",
     [
-        pytest.param({"files": [RemoteFile(uri="1", last_modified=datetime.strptime("2023-06-09T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ"))]}, hash(("stream", "2023-06-09T00:00:00.000000Z_1")), id="test_hash_with_slice"),
+        pytest.param(
+            {"files": [RemoteFile(uri="1", last_modified=datetime.strptime("2023-06-09T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ"))]},
+            hash(("stream", "2023-06-09T00:00:00.000000Z_1")),
+            id="test_hash_with_slice",
+        ),
         pytest.param(None, hash("stream"), id="test_hash_no_slice"),
     ],
 )
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_file_based_concurrent_cursor.py b/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_file_based_concurrent_cursor.py
index 2bf39894b12a..027038b2ae98 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_file_based_concurrent_cursor.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/stream/concurrent/test_file_based_concurrent_cursor.py
@@ -45,26 +45,17 @@ def _make_cursor(input_state: Optional[MutableMapping[str, Any]]) -> FileBasedCo
         pytest.param({}, (datetime.min, ""), id="no-state-gives-min-cursor"),
         pytest.param({"history": {}}, (datetime.min, ""), id="missing-cursor-field-gives-min-cursor"),
         pytest.param(
-            {
-                "history": {"a.csv": "2021-01-01T00:00:00.000000Z"},
-                "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"
-            },
+            {"history": {"a.csv": "2021-01-01T00:00:00.000000Z"}, "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"},
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             id="cursor-value-matches-earliest-file",
         ),
         pytest.param(
-            {
-                "history": {"a.csv": "2021-01-01T00:00:00.000000Z"},
-                "_ab_source_file_last_modified": "2020-01-01T00:00:00.000000Z_a.csv"
-            },
+            {"history": {"a.csv": "2021-01-01T00:00:00.000000Z"}, "_ab_source_file_last_modified": "2020-01-01T00:00:00.000000Z_a.csv"},
             (datetime.strptime("2020-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             id="cursor-value-is-earlier",
         ),
         pytest.param(
-            {
-                "history": {"a.csv": "2022-01-01T00:00:00.000000Z"},
-                "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"
-            },
+            {"history": {"a.csv": "2022-01-01T00:00:00.000000Z"}, "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"},
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             id="cursor-value-is-later",
         ),
@@ -73,30 +64,24 @@ def _make_cursor(input_state: Optional[MutableMapping[str, Any]]) -> FileBasedCo
                 "history": {
                     "a.csv": "2021-01-01T00:00:00.000000Z",
                     "b.csv": "2021-01-02T00:00:00.000000Z",
-                    "c.csv": "2021-01-03T00:00:00.000000Z"
+                    "c.csv": "2021-01-03T00:00:00.000000Z",
                 },
-                "_ab_source_file_last_modified": "2021-01-04T00:00:00.000000Z_d.csv"
+                "_ab_source_file_last_modified": "2021-01-04T00:00:00.000000Z_d.csv",
             },
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             id="cursor-not-earliest",
         ),
         pytest.param(
-            {
-                "history": {"b.csv": "2020-12-31T00:00:00.000000Z"},
-                "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"
-            },
+            {"history": {"b.csv": "2020-12-31T00:00:00.000000Z"}, "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"},
             (datetime.strptime("2020-12-31T00:00:00.000000Z", DATE_TIME_FORMAT), "b.csv"),
-            id="state-with-cursor-and-earlier-history"
+            id="state-with-cursor-and-earlier-history",
         ),
         pytest.param(
-            {
-                "history": {"b.csv": "2021-01-02T00:00:00.000000Z"},
-                "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"
-            },
+            {"history": {"b.csv": "2021-01-02T00:00:00.000000Z"}, "_ab_source_file_last_modified": "2021-01-01T00:00:00.000000Z_a.csv"},
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
-            id="state-with-cursor-and-later-history"
+            id="state-with-cursor-and-later-history",
         ),
-    ]
+    ],
 )
 def test_compute_prev_sync_cursor(input_state: MutableMapping[str, Any], expected_cursor_value: Tuple[datetime, str]):
     cursor = _make_cursor(input_state)
@@ -160,7 +145,7 @@ def test_compute_prev_sync_cursor(input_state: MutableMapping[str, Any], expecte
             "2022-01-05T00:00:00.000000Z_pending.csv",
             id="add-to-nonempty-history-pending-file-is-newer",
         ),
-    ]
+    ],
 )
 def test_add_file(
     initial_state: MutableMapping[str, Any],
@@ -175,23 +160,31 @@ def test_add_file(
     cursor._message_repository = mock_message_repository
     stream = MagicMock()
 
-    cursor.set_pending_partitions([
-        FileBasedStreamPartition(
-            stream,
-            {"files": [RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT))]},
-            mock_message_repository,
-            SyncMode.full_refresh,
-            FileBasedConcurrentCursor.CURSOR_FIELD,
-            initial_state,
-            cursor
-        ) for uri, timestamp in pending_files
-    ])
+    cursor.set_pending_partitions(
+        [
+            FileBasedStreamPartition(
+                stream,
+                {"files": [RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT))]},
+                mock_message_repository,
+                SyncMode.full_refresh,
+                FileBasedConcurrentCursor.CURSOR_FIELD,
+                initial_state,
+                cursor,
+            )
+            for uri, timestamp in pending_files
+        ]
+    )
 
     uri, timestamp = file_to_add
     cursor.add_file(RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)))
     assert cursor._file_to_datetime_history == expected_history
-    assert cursor._pending_files == {uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in expected_pending_files}
-    assert mock_message_repository.emit_message.call_args_list[0].args[0].state.data["test"]["_ab_source_file_last_modified"] == expected_cursor_value
+    assert cursor._pending_files == {
+        uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in expected_pending_files
+    }
+    assert (
+        mock_message_repository.emit_message.call_args_list[0].args[0].state.data["test"]["_ab_source_file_last_modified"]
+        == expected_cursor_value
+    )
 
 
 @pytest.mark.parametrize(
@@ -215,7 +208,7 @@ def test_add_file(
             "2021-01-05T00:00:00.000000Z_pending.csv",
             id="add-to-empty-history-file-not-in-pending-files",
         ),
-    ]
+    ],
 )
 def test_add_file_invalid(
     initial_state: MutableMapping[str, Any],
@@ -226,16 +219,23 @@ def test_add_file_invalid(
     expected_cursor_value: str,
 ):
     cursor = _make_cursor(initial_state)
-    cursor._pending_files = {uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in pending_files}
+    cursor._pending_files = {
+        uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in pending_files
+    }
     mock_message_repository = MagicMock()
     cursor._message_repository = mock_message_repository
 
     uri, timestamp = file_to_add
     cursor.add_file(RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)))
     assert cursor._file_to_datetime_history == expected_history
-    assert cursor._pending_files == {uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in expected_pending_files}
+    assert cursor._pending_files == {
+        uri: RemoteFile(uri=uri, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT)) for uri, timestamp in expected_pending_files
+    }
     assert mock_message_repository.emit_message.call_args_list[0].args[0].log.level.value == "WARN"
-    assert mock_message_repository.emit_message.call_args_list[1].args[0].state.data["test"]["_ab_source_file_last_modified"] == expected_cursor_value
+    assert (
+        mock_message_repository.emit_message.call_args_list[1].args[0].state.data["test"]["_ab_source_file_last_modified"]
+        == expected_cursor_value
+    )
 
 
 @pytest.mark.parametrize(
@@ -243,37 +243,33 @@ def test_add_file_invalid(
     [
         pytest.param({}, [], f"{datetime.min.strftime('%Y-%m-%dT%H:%M:%S.%fZ')}_", id="no-state-no-pending"),
         pytest.param(
-            {"history": {"a.csv": "2021-01-01T00:00:00.000000Z"}},
-            [],
-            "2021-01-01T00:00:00.000000Z_a.csv",
-            id="no-pending-with-history"
+            {"history": {"a.csv": "2021-01-01T00:00:00.000000Z"}}, [], "2021-01-01T00:00:00.000000Z_a.csv", id="no-pending-with-history"
         ),
         pytest.param(
-            {"history": {}},
-            [("b.csv", "2021-01-02T00:00:00.000000Z")],
-            "2021-01-02T00:00:00.000000Z_b.csv",
-            id="pending-no-history"
+            {"history": {}}, [("b.csv", "2021-01-02T00:00:00.000000Z")], "2021-01-02T00:00:00.000000Z_b.csv", id="pending-no-history"
         ),
         pytest.param(
             {"history": {"a.csv": "2022-01-01T00:00:00.000000Z"}},
             [("b.csv", "2021-01-02T00:00:00.000000Z")],
             "2021-01-01T00:00:00.000000Z_a.csv",
-            id="with-pending-before-history"
+            id="with-pending-before-history",
         ),
         pytest.param(
             {"history": {"a.csv": "2021-01-01T00:00:00.000000Z"}},
             [("b.csv", "2022-01-02T00:00:00.000000Z")],
             "2022-01-01T00:00:00.000000Z_a.csv",
-            id="with-pending-after-history"
+            id="with-pending-after-history",
         ),
-    ]
+    ],
 )
 def test_get_new_cursor_value(input_state: MutableMapping[str, Any], pending_files: List[Tuple[str, str]], expected_cursor_value: str):
     cursor = _make_cursor(input_state)
     pending_partitions = []
     for url, timestamp in pending_files:
         partition = MagicMock()
-        partition.to_slice = lambda *args, **kwargs: {"files": [RemoteFile(uri=url, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT))]}
+        partition.to_slice = lambda *args, **kwargs: {
+            "files": [RemoteFile(uri=url, last_modified=datetime.strptime(timestamp, DATE_TIME_FORMAT))]
+        }
         pending_partitions.append(partition)
 
     cursor.set_pending_partitions(pending_partitions)
@@ -288,7 +284,7 @@ def test_get_new_cursor_value(input_state: MutableMapping[str, Any], pending_fil
             False,
             (datetime.min, ""),
             ["new.csv"],
-            id="empty-history-one-new-file"
+            id="empty-history-one-new-file",
         ),
         pytest.param(
             [RemoteFile(uri="a.csv", last_modified=datetime.strptime("2021-01-02T00:00:00.000000Z", "%Y-%m-%dT%H:%M:%S.%fZ"))],
@@ -296,7 +292,7 @@ def test_get_new_cursor_value(input_state: MutableMapping[str, Any], pending_fil
             False,
             (datetime.min, ""),
             ["a.csv"],
-            id="non-empty-history-file-in-history-modified"
+            id="non-empty-history-file-in-history-modified",
         ),
         pytest.param(
             [RemoteFile(uri="a.csv", last_modified=datetime.strptime("2021-01-01T00:00:00.000000Z", "%Y-%m-%dT%H:%M:%S.%fZ"))],
@@ -304,9 +300,9 @@ def test_get_new_cursor_value(input_state: MutableMapping[str, Any], pending_fil
             False,
             (datetime.min, ""),
             [],
-            id="non-empty-history-file-in-history-not-modified"
+            id="non-empty-history-file-in-history-not-modified",
         ),
-    ]
+    ],
 )
 def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_value, expected_files_to_sync):
     cursor = _make_cursor({})
@@ -328,7 +324,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.min, ""),
             datetime.min,
             True,
-            id="file-not-in-history-not-full-old-cursor"
+            id="file-not-in-history-not-full-old-cursor",
         ),
         pytest.param(
             RemoteFile(uri="new.csv", last_modified=datetime.strptime("2021-01-03T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -337,7 +333,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2024-01-02T00:00:00.000000Z", DATE_TIME_FORMAT), ""),
             datetime.min,
             True,
-            id="file-not-in-history-not-full-new-cursor"
+            id="file-not-in-history-not-full-new-cursor",
         ),
         pytest.param(
             RemoteFile(uri="a.csv", last_modified=datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -346,7 +342,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.min, ""),
             datetime.min,
             False,
-            id="file-in-history-not-modified"
+            id="file-in-history-not-modified",
         ),
         pytest.param(
             RemoteFile(uri="a.csv", last_modified=datetime.strptime("2020-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -355,7 +351,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.min, ""),
             datetime.min,
             False,
-            id="file-in-history-modified-before"
+            id="file-in-history-modified-before",
         ),
         pytest.param(
             RemoteFile(uri="a.csv", last_modified=datetime.strptime("2022-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -364,7 +360,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.min, ""),
             datetime.min,
             True,
-            id="file-in-history-modified-after"
+            id="file-in-history-modified-after",
         ),
         pytest.param(
             RemoteFile(uri="new.csv", last_modified=datetime.strptime("2022-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -373,7 +369,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2021-01-02T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             datetime.min,
             True,
-            id="history-full-file-modified-after-cursor"
+            id="history-full-file-modified-after-cursor",
         ),
         pytest.param(
             RemoteFile(uri="new1.csv", last_modified=datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -382,7 +378,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "new0.csv"),
             datetime.min,
             True,
-            id="history-full-modified-eq-cursor-uri-gt"
+            id="history-full-modified-eq-cursor-uri-gt",
         ),
         pytest.param(
             RemoteFile(uri="new0.csv", last_modified=datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -391,7 +387,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "new1.csv"),
             datetime.min,
             False,
-            id="history-full-modified-eq-cursor-uri-lt"
+            id="history-full-modified-eq-cursor-uri-lt",
         ),
         pytest.param(
             RemoteFile(uri="new.csv", last_modified=datetime.strptime("2020-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -400,7 +396,7 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             datetime.min,
             True,
-            id="history-full-modified-before-cursor-and-after-sync-start"
+            id="history-full-modified-before-cursor-and-after-sync-start",
         ),
         pytest.param(
             RemoteFile(uri="new.csv", last_modified=datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT)),
@@ -409,9 +405,9 @@ def test_get_files_to_sync(all_files, history, is_history_full, prev_cursor_valu
             (datetime.strptime("2022-01-01T00:00:00.000000Z", DATE_TIME_FORMAT), "a.csv"),
             datetime.strptime("2024-01-01T00:00:00.000000Z", DATE_TIME_FORMAT),
             False,
-            id="history-full-modified-before-cursor-and-before-sync-start"
+            id="history-full-modified-before-cursor-and-before-sync-start",
         ),
-    ]
+    ],
 )
 def test_should_sync_file(
     file_to_check: RemoteFile,
@@ -439,21 +435,21 @@ def test_should_sync_file(
             {"a.csv": "2021-01-01T00:00:00.000000Z"},
             False,
             datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT),
-            id="non-full-history"
+            id="non-full-history",
         ),
         pytest.param(
             {f"file{i}.csv": f"2021-01-0{i}T00:00:00.000000Z" for i in range(1, 4)},  # all before the time window
             True,
             datetime.strptime("2021-01-01T00:00:00.000000Z", DATE_TIME_FORMAT),  # Time window start time
-            id="full-history-earliest-before-window"
+            id="full-history-earliest-before-window",
         ),
         pytest.param(
             {f"file{i}.csv": f"2024-01-0{i}T00:00:00.000000Z" for i in range(1, 4)},  # all after the time window
             True,
             datetime.strptime("2023-06-13T00:00:00.000000Z", DATE_TIME_FORMAT),  # Earliest file time
-            id="full-history-earliest-after-window"
+            id="full-history-earliest-after-window",
         ),
-    ]
+    ],
 )
 def test_compute_start_time(input_history, is_history_full, expected_start_time, monkeypatch):
     cursor = _make_cursor({"history": input_history})
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/stream/test_default_file_based_stream.py b/airbyte-cdk/python/unit_tests/sources/file_based/stream/test_default_file_based_stream.py
index be36413f271b..e93eb6bbfc5e 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/stream/test_default_file_based_stream.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/stream/test_default_file_based_stream.py
@@ -66,9 +66,7 @@ class MockFormat:
         ),
     ],
 )
-def test_fill_nulls(
-    input_schema: Mapping[str, Any], expected_output: Mapping[str, Any]
-) -> None:
+def test_fill_nulls(input_schema: Mapping[str, Any], expected_output: Mapping[str, Any]) -> None:
     assert DefaultFileBasedStream._fill_nulls(input_schema) == expected_output
 
 
@@ -103,14 +101,8 @@ def setUp(self) -> None:
 
     def test_when_read_records_from_slice_then_return_records(self) -> None:
         self._parser.parse_records.return_value = [self._A_RECORD]
-        messages = list(
-            self._stream.read_records_from_slice(
-                {"files": [RemoteFile(uri="uri", last_modified=self._NOW)]}
-            )
-        )
-        assert list(map(lambda message: message.record.data["data"], messages)) == [
-            self._A_RECORD
-        ]
+        messages = list(self._stream.read_records_from_slice({"files": [RemoteFile(uri="uri", last_modified=self._NOW)]}))
+        assert list(map(lambda message: message.record.data["data"], messages)) == [self._A_RECORD]
 
     def test_given_exception_when_read_records_from_slice_then_do_process_other_files(
         self,
@@ -165,9 +157,7 @@ def test_given_exception_after_skipping_records_when_read_records_from_slice_the
     ) -> None:
         self._stream_config.schemaless = False
         self._validation_policy.record_passes_validation_policy.return_value = False
-        self._parser.parse_records.side_effect = [
-            self._iter([self._A_RECORD, ValueError("An error")])
-        ]
+        self._parser.parse_records.side_effect = [self._iter([self._A_RECORD, ValueError("An error")])]
 
         messages = list(
             self._stream.read_records_from_slice(
@@ -225,9 +215,7 @@ class TestFileBasedErrorCollector:
             "Multiple errors",
         ],
     )
-    def test_collect_parsing_error(
-        self, stream, file, line_no, n_skipped, collector_expected_len
-    ) -> None:
+    def test_collect_parsing_error(self, stream, file, line_no, n_skipped, collector_expected_len) -> None:
         test_error_pattern = "Error parsing record."
         # format the error body
         test_error = (
@@ -252,11 +240,5 @@ def test_yield_and_raise_collected(self) -> None:
         # we expect the following method will raise the AirbyteTracedException
         with pytest.raises(AirbyteTracedException) as parse_error:
             list(self.test_error_collector.yield_and_raise_collected())
-        assert (
-            parse_error.value.message
-            == "Some errors occured while reading from the source."
-        )
-        assert (
-            parse_error.value.internal_message
-            == "Please check the logged errors for more information."
-        )
+        assert parse_error.value.message == "Some errors occured while reading from the source."
+        assert parse_error.value.internal_message == "Please check the logged errors for more information."
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/test_file_based_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/test_file_based_scenarios.py
index dfcea11f815e..5a7a7b72ff9b 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/test_file_based_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/test_file_based_scenarios.py
@@ -258,7 +258,6 @@
     single_csv_input_state_is_earlier_scenario_concurrent,
     single_csv_input_state_is_later_scenario_concurrent,
     single_csv_no_input_state_scenario_concurrent,
-
 ]
 
 read_scenarios = discover_scenarios + [
diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/test_scenarios.py b/airbyte-cdk/python/unit_tests/sources/file_based/test_scenarios.py
index e4d0aae7dacd..47df14a09403 100644
--- a/airbyte-cdk/python/unit_tests/sources/file_based/test_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/file_based/test_scenarios.py
@@ -80,11 +80,15 @@ def _verify_read_output(output: EntrypointOutput, scenario: TestScenario[Abstrac
 
     sorted_expected_records = sorted(
         filter(lambda e: "data" in e, expected_records),
-        key=lambda record: ",".join(f"{k}={v}" for k, v in sorted(record["data"].items(), key=lambda items: (items[0], items[1])) if k != "emitted_at"),
+        key=lambda record: ",".join(
+            f"{k}={v}" for k, v in sorted(record["data"].items(), key=lambda items: (items[0], items[1])) if k != "emitted_at"
+        ),
     )
     sorted_records = sorted(
         filter(lambda r: r.record, records),
-        key=lambda record: ",".join(f"{k}={v}" for k, v in sorted(record.record.data.items(), key=lambda items: (items[0], items[1])) if k != "emitted_at"),
+        key=lambda record: ",".join(
+            f"{k}={v}" for k, v in sorted(record.record.data.items(), key=lambda items: (items[0], items[1])) if k != "emitted_at"
+        ),
     )
 
     assert len(sorted_records) == len(sorted_expected_records)
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/incremental_scenarios.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/incremental_scenarios.py
index 08df8db39b7f..af3161e07199 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/incremental_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/incremental_scenarios.py
@@ -163,10 +163,17 @@
 )
 
 
-CONCURRENT_STATE = StateBuilder().with_stream_state("stream1", {
-    "slices": [{"start": 0, "end": 0}],
-    "state_type": ConcurrencyCompatibleStateType.date_range.value,
-}).build()
+CONCURRENT_STATE = (
+    StateBuilder()
+    .with_stream_state(
+        "stream1",
+        {
+            "slices": [{"start": 0, "end": 0}],
+            "state_type": ConcurrencyCompatibleStateType.date_range.value,
+        },
+    )
+    .build()
+)
 test_incremental_stream_without_slice_boundaries_with_concurrent_state = (
     TestScenarioBuilder()
     .set_name("test_incremental_stream_without_slice_boundaries_with_concurrent_state")
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/stream_facade_scenarios.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/stream_facade_scenarios.py
index 2080126a509e..8964024d2ca0 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/stream_facade_scenarios.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/scenarios/stream_facade_scenarios.py
@@ -357,7 +357,7 @@
         [
             {"data": {"id": "1", "cursor_field": 0}, "stream": "stream1"},
             {"data": {"id": "2", "cursor_field": 1}, "stream": "stream1"},
-            {"stream1": {'cursor_field': 1}},
+            {"stream1": {"cursor_field": 1}},
             {"data": {"id": "3", "cursor_field": 2}, "stream": "stream1"},
             {"data": {"id": "4", "cursor_field": 3}, "stream": "stream1"},
             {"stream1": {"cursor_field": 2}},
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_concurrent_read_processor.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_concurrent_read_processor.py
index f03fe0c0eb43..3e0e00b62d32 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_concurrent_read_processor.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_concurrent_read_processor.py
@@ -113,7 +113,7 @@ def test_handle_partition_done_no_other_streams_to_generate_partitions_for(self)
     def test_handle_last_stream_partition_done(self):
         in_order_validation_mock = Mock()
         in_order_validation_mock.attach_mock(self._another_stream, "_another_stream")
-        in_order_validation_mock.attach_mock(self._message_repository, '_message_repository')
+        in_order_validation_mock.attach_mock(self._message_repository, "_message_repository")
         self._message_repository.consume_queue.return_value = iter([_ANY_AIRBYTE_MESSAGE])
         stream_instances_to_read_from = [self._another_stream]
 
@@ -143,10 +143,12 @@ def test_handle_last_stream_partition_done(self):
                         status=AirbyteStreamStatus(AirbyteStreamStatus.COMPLETE),
                     ),
                 ),
-            )
+            ),
         ]
         assert expected_messages == messages
-        assert in_order_validation_mock.mock_calls.index(call._another_stream.cursor.ensure_at_least_one_state_emitted) < in_order_validation_mock.mock_calls.index(call._message_repository.consume_queue)
+        assert in_order_validation_mock.mock_calls.index(
+            call._another_stream.cursor.ensure_at_least_one_state_emitted
+        ) < in_order_validation_mock.mock_calls.index(call._message_repository.consume_queue)
 
     def test_handle_partition(self):
         stream_instances_to_read_from = [self._another_stream]
@@ -525,10 +527,11 @@ def test_on_exception_stops_streams_and_raises_an_exception(self):
                     type=TraceType.STREAM_STATUS,
                     emitted_at=1577836800000.0,
                     stream_status=AirbyteStreamStatusTraceMessage(
-                        stream_descriptor=StreamDescriptor(name=_ANOTHER_STREAM_NAME), status=AirbyteStreamStatus(AirbyteStreamStatus.INCOMPLETE)
+                        stream_descriptor=StreamDescriptor(name=_ANOTHER_STREAM_NAME),
+                        status=AirbyteStreamStatus(AirbyteStreamStatus.INCOMPLETE),
                     ),
                 ),
-            )
+            ),
         ]
 
         assert messages == expected_message
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_cursor.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_cursor.py
index dd1246fbc2a8..94ed5211eabb 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_cursor.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_cursor.py
@@ -112,7 +112,7 @@ def test_given_no_boundary_fields_when_close_partition_then_emit_state(self) ->
         self._state_manager.update_state_for_stream.assert_called_once_with(
             _A_STREAM_NAME,
             _A_STREAM_NAMESPACE,
-            {'a_cursor_field_key': 10},
+            {"a_cursor_field_key": 10},
         )
 
     def test_given_no_boundary_fields_when_close_multiple_partitions_then_raise_exception(self) -> None:
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_datetime_state_converter.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_datetime_state_converter.py
index b516afaeef62..534dbd580787 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_datetime_state_converter.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_datetime_state_converter.py
@@ -94,72 +94,72 @@ def test_concurrent_stream_state_converter_is_state_message_compatible(converter
             None,
             {},
             EpochValueConcurrentStreamStateConverter().zero_value,
-            id="epoch-converter-no-state-no-start-start-is-zero-value"
+            id="epoch-converter-no-state-no-start-start-is-zero-value",
         ),
         pytest.param(
             EpochValueConcurrentStreamStateConverter(),
             1617030403,
             {},
             datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
-            id="epoch-converter-no-state-with-start-start-is-start"
+            id="epoch-converter-no-state-with-start-start-is-start",
         ),
         pytest.param(
             EpochValueConcurrentStreamStateConverter(),
             None,
             {"created_at": 1617030404},
             datetime(2021, 3, 29, 15, 6, 44, tzinfo=timezone.utc),
-            id="epoch-converter-state-without-start-start-is-from-state"
+            id="epoch-converter-state-without-start-start-is-from-state",
         ),
         pytest.param(
             EpochValueConcurrentStreamStateConverter(),
             1617030404,
             {"created_at": 1617030403},
             datetime(2021, 3, 29, 15, 6, 44, tzinfo=timezone.utc),
-            id="epoch-converter-state-before-start-start-is-start"
+            id="epoch-converter-state-before-start-start-is-start",
         ),
         pytest.param(
             EpochValueConcurrentStreamStateConverter(),
             1617030403,
             {"created_at": 1617030404},
             datetime(2021, 3, 29, 15, 6, 44, tzinfo=timezone.utc),
-            id="epoch-converter-state-after-start-start-is-from-state"
+            id="epoch-converter-state-after-start-start-is-from-state",
         ),
         pytest.param(
             IsoMillisConcurrentStreamStateConverter(),
             None,
             {},
             IsoMillisConcurrentStreamStateConverter().zero_value,
-            id="isomillis-converter-no-state-no-start-start-is-zero-value"
+            id="isomillis-converter-no-state-no-start-start-is-zero-value",
         ),
         pytest.param(
             IsoMillisConcurrentStreamStateConverter(),
             "2021-08-22T05:03:27.000Z",
             {},
             datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
-            id="isomillis-converter-no-state-with-start-start-is-start"
+            id="isomillis-converter-no-state-with-start-start-is-start",
         ),
         pytest.param(
             IsoMillisConcurrentStreamStateConverter(),
             None,
             {"created_at": "2021-08-22T05:03:27.000Z"},
             datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
-            id="isomillis-converter-state-without-start-start-is-from-state"
+            id="isomillis-converter-state-without-start-start-is-from-state",
         ),
         pytest.param(
             IsoMillisConcurrentStreamStateConverter(),
             "2022-08-22T05:03:27.000Z",
             {"created_at": "2021-08-22T05:03:27.000Z"},
             datetime(2022, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
-            id="isomillis-converter-state-before-start-start-is-start"
+            id="isomillis-converter-state-before-start-start-is-start",
         ),
         pytest.param(
             IsoMillisConcurrentStreamStateConverter(),
             "2022-08-22T05:03:27.000Z",
             {"created_at": "2023-08-22T05:03:27.000Z"},
             datetime(2023, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
-            id="isomillis-converter-state-after-start-start-is-from-state"
+            id="isomillis-converter-state-after-start-start-is-from-state",
         ),
-    ]
+    ],
 )
 def test_get_sync_start(converter, start, state, expected_start):
     assert converter._get_sync_start(CursorField("created_at"), state, start) == expected_start
@@ -174,8 +174,12 @@ def test_get_sync_start(converter, start, state, expected_start):
             {},
             {
                 "legacy": {},
-                "slices": [{"start": EpochValueConcurrentStreamStateConverter().zero_value,
-                            "end": EpochValueConcurrentStreamStateConverter().zero_value}],
+                "slices": [
+                    {
+                        "start": EpochValueConcurrentStreamStateConverter().zero_value,
+                        "end": EpochValueConcurrentStreamStateConverter().zero_value,
+                    }
+                ],
                 "state_type": "date-range",
             },
             id="empty-input-state-epoch",
@@ -186,8 +190,12 @@ def test_get_sync_start(converter, start, state, expected_start):
             {"created": 1617030403},
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    }
+                ],
                 "legacy": {"created": 1617030403},
             },
             id="with-input-state-epoch",
@@ -198,8 +206,12 @@ def test_get_sync_start(converter, start, state, expected_start):
             {"created": "2021-08-22T05:03:27.000Z"},
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
-                            "end": datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
+                        "end": datetime(2021, 8, 22, 5, 3, 27, tzinfo=timezone.utc),
+                    }
+                ],
                 "legacy": {"created": "2021-08-22T05:03:27.000Z"},
             },
             id="with-input-state-isomillis",
@@ -227,8 +239,12 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             EpochValueConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 3, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 3, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    }
+                ],
             },
             {"created": 1617030403},
             id="epoch-single-slice",
@@ -237,10 +253,16 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             EpochValueConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)},
-                           {"start": datetime(2020, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2022, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                    {
+                        "start": datetime(2020, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2022, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                ],
             },
             {"created": 1648566403},
             id="epoch-overlapping-slices",
@@ -249,10 +271,16 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             EpochValueConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)},
-                           {"start": datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                           "end": datetime(2023, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                    {
+                        "start": datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2023, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                ],
             },
             {"created": 1617030403},
             id="epoch-multiple-slices",
@@ -261,8 +289,12 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             IsoMillisConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 3, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 3, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    }
+                ],
             },
             {"created": "2021-03-29T15:06:43.000Z"},
             id="isomillis-single-slice",
@@ -271,10 +303,16 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             IsoMillisConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)},
-                           {"start": datetime(2020, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2022, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                    {
+                        "start": datetime(2020, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2022, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                ],
             },
             {"created": "2022-03-29T15:06:43.000Z"},
             id="isomillis-overlapping-slices",
@@ -283,10 +321,16 @@ def test_convert_from_sequential_state(converter, start, sequential_state, expec
             IsoMillisConcurrentStreamStateConverter(),
             {
                 "state_type": "date-range",
-                "slices": [{"start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                            "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc)},
-                           {"start": datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
-                           "end": datetime(2023, 3, 29, 15, 6, 43, tzinfo=timezone.utc)}],
+                "slices": [
+                    {
+                        "start": datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2021, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                    {
+                        "start": datetime(2022, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
+                        "end": datetime(2023, 3, 29, 15, 6, 43, tzinfo=timezone.utc),
+                    },
+                ],
             },
             {"created": "2021-03-29T15:06:43.000Z"},
             id="isomillis-multiple-slices",
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_enqueuer.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_enqueuer.py
index 5b832adeaec0..bdcd9ad43318 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_enqueuer.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_enqueuer.py
@@ -71,6 +71,7 @@ def inner_function() -> Iterable[Partition]:
             for partition in partitions:
                 yield partition
             raise exception
+
         return inner_function
 
     @staticmethod
diff --git a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_reader.py b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_reader.py
index 4b0742f991a1..9e9fb8973949 100644
--- a/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_reader.py
+++ b/airbyte-cdk/python/unit_tests/sources/streams/concurrent/test_partition_reader.py
@@ -63,4 +63,5 @@ def _read_with_exception(records: List[Record], exception: Exception) -> Callabl
         def mocked_function() -> Iterable[Record]:
             yield from records
             raise exception
+
         return mocked_function
diff --git a/airbyte-cdk/python/unit_tests/sources/test_abstract_source.py b/airbyte-cdk/python/unit_tests/sources/test_abstract_source.py
index f184fe505802..f1489c43860a 100644
--- a/airbyte-cdk/python/unit_tests/sources/test_abstract_source.py
+++ b/airbyte-cdk/python/unit_tests/sources/test_abstract_source.py
@@ -372,17 +372,19 @@ def _as_state(state_data: Dict[str, Any], stream_name: str = "", per_stream_stat
     return AirbyteMessage(type=Type.STATE, state=AirbyteStateMessage(data=state_data))
 
 
-def _as_error_trace(stream: str, error_message: str,  internal_message: Optional[str], failure_type: Optional[FailureType], stack_trace: Optional[str]) -> AirbyteMessage:
+def _as_error_trace(
+    stream: str, error_message: str, internal_message: Optional[str], failure_type: Optional[FailureType], stack_trace: Optional[str]
+) -> AirbyteMessage:
     trace_message = AirbyteTraceMessage(
         emitted_at=datetime.datetime.now().timestamp() * 1000.0,
         type=TraceType.ERROR,
         error=AirbyteErrorTraceMessage(
-                stream_descriptor=StreamDescriptor(name=stream),
-                message=error_message,
-                internal_message=internal_message,
-                failure_type=failure_type,
-                stack_trace=stack_trace,
-            ),
+            stream_descriptor=StreamDescriptor(name=stream),
+            message=error_message,
+            internal_message=internal_message,
+            failure_type=failure_type,
+            stack_trace=stack_trace,
+        ),
     )
 
     return AirbyteMessage(type=MessageType.TRACE, trace=trace_message)
@@ -1186,8 +1188,12 @@ def test_checkpoint_state_from_stream_instance():
     managers_stream = StreamNoStateMethod()
     state_manager = ConnectorStateManager(
         {
-            "teams": AirbyteStream(name="teams", namespace="", json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental]),
-            "managers": AirbyteStream(name="managers", namespace="", json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental])
+            "teams": AirbyteStream(
+                name="teams", namespace="", json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental]
+            ),
+            "managers": AirbyteStream(
+                name="managers", namespace="", json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental]
+            ),
         },
         [],
     )
@@ -1207,9 +1213,19 @@ def test_checkpoint_state_from_stream_instance():
 @pytest.mark.parametrize(
     "exception_to_raise,expected_error_message,expected_internal_message",
     [
-        pytest.param(AirbyteTracedException(message="I was born only to crash like Icarus"), "I was born only to crash like Icarus", None, id="test_raises_traced_exception"),
-        pytest.param(Exception("Generic connector error message"), "Something went wrong in the connector. See the logs for more details.", "Generic connector error message", id="test_raises_generic_exception"),
-    ]
+        pytest.param(
+            AirbyteTracedException(message="I was born only to crash like Icarus"),
+            "I was born only to crash like Icarus",
+            None,
+            id="test_raises_traced_exception",
+        ),
+        pytest.param(
+            Exception("Generic connector error message"),
+            "Something went wrong in the connector. See the logs for more details.",
+            "Generic connector error message",
+            id="test_raises_generic_exception",
+        ),
+    ],
 )
 def test_continue_sync_with_failed_streams(mocker, exception_to_raise, expected_error_message, expected_internal_message):
     """
@@ -1317,7 +1333,9 @@ def test_sync_error_trace_messages_obfuscate_secrets(mocker):
 
     stream_output = [{"k1": "v1"}, {"k2": "v2"}]
     s1 = MockStream([({"sync_mode": SyncMode.full_refresh}, stream_output)], name="s1")
-    s2 = StreamRaisesException(exception_to_raise=AirbyteTracedException(message="My api_key value API_KEY_VALUE flew too close to the sun."))
+    s2 = StreamRaisesException(
+        exception_to_raise=AirbyteTracedException(message="My api_key value API_KEY_VALUE flew too close to the sun.")
+    )
     s3 = MockStream([({"sync_mode": SyncMode.full_refresh}, stream_output)], name="s3")
 
     mocker.patch.object(MockStream, "get_json_schema", return_value={})
diff --git a/airbyte-cdk/python/unit_tests/sources/test_connector_state_manager.py b/airbyte-cdk/python/unit_tests/sources/test_connector_state_manager.py
index 3b7edc3e9991..9bee58eb69ee 100644
--- a/airbyte-cdk/python/unit_tests/sources/test_connector_state_manager.py
+++ b/airbyte-cdk/python/unit_tests/sources/test_connector_state_manager.py
@@ -158,7 +158,10 @@
 def test_initialize_state_manager(input_stream_state, expected_stream_state, expected_error):
     stream_to_instance_map = {
         "actors": AirbyteStream(
-            name="actors", namespace="public", json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental],
+            name="actors",
+            namespace="public",
+            json_schema={},
+            supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental],
         )
     }
 
@@ -268,7 +271,8 @@ def test_initialize_state_manager(input_stream_state, expected_stream_state, exp
     ],
 )
 def test_get_stream_state(input_state, stream_name, namespace, expected_state):
-    stream_to_instance_map = {stream_name: AirbyteStream(
+    stream_to_instance_map = {
+        stream_name: AirbyteStream(
             name=stream_name, namespace=namespace, json_schema={}, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental]
         )
     }
diff --git a/airbyte-cdk/python/unit_tests/test/test_entrypoint_wrapper.py b/airbyte-cdk/python/unit_tests/test/test_entrypoint_wrapper.py
index 08797e763d37..d0564cdf93f6 100644
--- a/airbyte-cdk/python/unit_tests/test/test_entrypoint_wrapper.py
+++ b/airbyte-cdk/python/unit_tests/test/test_entrypoint_wrapper.py
@@ -29,10 +29,7 @@
 
 
 def _a_state_message(state: Any) -> AirbyteMessage:
-    return AirbyteMessage(
-        type=Type.STATE,
-        state=AirbyteStateMessage(data=state)
-    )
+    return AirbyteMessage(type=Type.STATE, state=AirbyteStateMessage(data=state))
 
 
 def _a_status_message(stream_name: str, status: AirbyteStreamStatus) -> AirbyteMessage:
@@ -50,14 +47,10 @@ def _a_status_message(stream_name: str, status: AirbyteStreamStatus) -> AirbyteM
 
 
 _A_RECORD = AirbyteMessage(
-    type=Type.RECORD,
-    record=AirbyteRecordMessage(stream="stream", data={"record key": "record value"}, emitted_at=0)
+    type=Type.RECORD, record=AirbyteRecordMessage(stream="stream", data={"record key": "record value"}, emitted_at=0)
 )
 _A_STATE_MESSAGE = _a_state_message({"state key": "state value for _A_STATE_MESSAGE"})
-_A_LOG = AirbyteMessage(
-    type=Type.LOG,
-    log=AirbyteLogMessage(level=Level.INFO, message="This is an Airbyte log message")
-)
+_A_LOG = AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="This is an Airbyte log message"))
 _AN_ERROR_MESSAGE = AirbyteMessage(
     type=Type.TRACE,
     trace=AirbyteTraceMessage(
@@ -121,6 +114,7 @@ def _validate_tmp_files(self):
         _validate_tmp_catalog(expected_catalog, entrypoint.return_value.parse_args.call_args.args[0][4])
         _validate_tmp_json_file(expected_state, entrypoint.return_value.parse_args.call_args.args[0][6])
         return entrypoint.return_value.run.return_value
+
     return _validate_tmp_files
 
 
@@ -154,6 +148,7 @@ def test_given_logging_during_run_when_read_then_output_has_logs(self, entrypoin
         def _do_some_logging(self):
             logging.getLogger("any logger").info(_A_LOG_MESSAGE)
             return entrypoint.return_value.run.return_value
+
         entrypoint.return_value.run.side_effect = _do_some_logging
 
         output = read(self._a_source, _A_CONFIG, _A_CATALOG, _A_STATE)
@@ -204,7 +199,7 @@ def test_given_trace_message_when_read_then_output_has_trace_messages(self, entr
     def test_given_stream_statuses_when_read_then_return_statuses(self, entrypoint):
         status_messages = [
             _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.STARTED),
-            _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.COMPLETE)
+            _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.COMPLETE),
         ]
         entrypoint.return_value.run.return_value = _to_entrypoint_output(status_messages)
         output = read(self._a_source, _A_CONFIG, _A_CATALOG, _A_STATE)
@@ -215,20 +210,20 @@ def test_given_stream_statuses_for_many_streams_when_read_then_filter_other_stre
         status_messages = [
             _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.STARTED),
             _a_status_message("another stream name", AirbyteStreamStatus.INCOMPLETE),
-            _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.COMPLETE)
+            _a_status_message(_A_STREAM_NAME, AirbyteStreamStatus.COMPLETE),
         ]
         entrypoint.return_value.run.return_value = _to_entrypoint_output(status_messages)
         output = read(self._a_source, _A_CONFIG, _A_CATALOG, _A_STATE)
         assert len(output.get_stream_statuses(_A_STREAM_NAME)) == 2
 
-    @patch('airbyte_cdk.test.entrypoint_wrapper.print', create=True)
+    @patch("airbyte_cdk.test.entrypoint_wrapper.print", create=True)
     @patch("airbyte_cdk.test.entrypoint_wrapper.AirbyteEntrypoint")
     def test_given_unexpected_exception_when_read_then_print(self, entrypoint, print_mock):
         entrypoint.return_value.run.side_effect = ValueError("This error should be printed")
         read(self._a_source, _A_CONFIG, _A_CATALOG, _A_STATE)
         assert print_mock.call_count > 0
 
-    @patch('airbyte_cdk.test.entrypoint_wrapper.print', create=True)
+    @patch("airbyte_cdk.test.entrypoint_wrapper.print", create=True)
     @patch("airbyte_cdk.test.entrypoint_wrapper.AirbyteEntrypoint")
     def test_given_expected_exception_when_read_then_do_not_print(self, entrypoint, print_mock):
         entrypoint.return_value.run.side_effect = ValueError("This error should be printed")
diff --git a/airbyte-cdk/python/unit_tests/test_entrypoint.py b/airbyte-cdk/python/unit_tests/test_entrypoint.py
index 61e7e7ec142a..7451a320d404 100644
--- a/airbyte-cdk/python/unit_tests/test_entrypoint.py
+++ b/airbyte-cdk/python/unit_tests/test_entrypoint.py
@@ -247,7 +247,9 @@ def test_run_read(entrypoint: AirbyteEntrypoint, mocker, spec_mock, config_mock)
     assert spec_mock.called
 
 
-def test_given_message_emitted_during_config_when_read_then_emit_message_before_next_steps(entrypoint: AirbyteEntrypoint, mocker, spec_mock, config_mock):
+def test_given_message_emitted_during_config_when_read_then_emit_message_before_next_steps(
+    entrypoint: AirbyteEntrypoint, mocker, spec_mock, config_mock
+):
     parsed_args = Namespace(command="read", config="config_path", state="statepath", catalog="catalogpath")
     mocker.patch.object(MockSource, "read_catalog", side_effect=ValueError)
 

From 34956a1285074d361a7c80e4c5abe2c550e2a81c Mon Sep 17 00:00:00 2001
From: artem1205 
Date: Thu, 22 Feb 2024 18:46:52 +0000
Subject: [PATCH 26/74] =?UTF-8?q?=F0=9F=A4=96=20Bump=20minor=20version=20o?=
 =?UTF-8?q?f=20Python=20CDK?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 airbyte-cdk/python/.bumpversion.cfg | 2 +-
 airbyte-cdk/python/CHANGELOG.md     | 3 +++
 airbyte-cdk/python/Dockerfile       | 4 ++--
 airbyte-cdk/python/setup.py         | 2 +-
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/airbyte-cdk/python/.bumpversion.cfg b/airbyte-cdk/python/.bumpversion.cfg
index 6389be4c7239..286c6a02b098 100644
--- a/airbyte-cdk/python/.bumpversion.cfg
+++ b/airbyte-cdk/python/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.65.0
+current_version = 0.66.0
 commit = False
 
 [bumpversion:file:setup.py]
diff --git a/airbyte-cdk/python/CHANGELOG.md b/airbyte-cdk/python/CHANGELOG.md
index 163c9bf4552b..bf0575a22c23 100644
--- a/airbyte-cdk/python/CHANGELOG.md
+++ b/airbyte-cdk/python/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Changelog
 
+## 0.66.0
+Low-code: Add interpolation for request options
+
 ## 0.65.0
 low-code: Allow connectors to ignore stream slicer request options on paginated requests
 
diff --git a/airbyte-cdk/python/Dockerfile b/airbyte-cdk/python/Dockerfile
index b84acc6873b6..d98aefd1ff43 100644
--- a/airbyte-cdk/python/Dockerfile
+++ b/airbyte-cdk/python/Dockerfile
@@ -10,7 +10,7 @@ RUN apk --no-cache upgrade \
     && apk --no-cache add tzdata build-base
 
 # install airbyte-cdk
-RUN pip install --prefix=/install airbyte-cdk==0.65.0
+RUN pip install --prefix=/install airbyte-cdk==0.66.0
 
 # build a clean environment
 FROM base
@@ -32,5 +32,5 @@ ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
 ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]
 
 # needs to be the same as CDK
-LABEL io.airbyte.version=0.65.0
+LABEL io.airbyte.version=0.66.0
 LABEL io.airbyte.name=airbyte/source-declarative-manifest
diff --git a/airbyte-cdk/python/setup.py b/airbyte-cdk/python/setup.py
index 7c7b12e7dd89..83405018d9e2 100644
--- a/airbyte-cdk/python/setup.py
+++ b/airbyte-cdk/python/setup.py
@@ -36,7 +36,7 @@
     name="airbyte-cdk",
     # The version of the airbyte-cdk package is used at runtime to validate manifests. That validation must be
     # updated if our semver format changes such as using release candidate versions.
-    version="0.65.0",
+    version="0.66.0",
     description="A framework for writing Airbyte Connectors.",
     long_description=README,
     long_description_content_type="text/markdown",

From dd1991ea52ebb5da55ef7820edad09bd10706a7c Mon Sep 17 00:00:00 2001
From: Brian Leonard 
Date: Thu, 22 Feb 2024 10:49:06 -0800
Subject: [PATCH 27/74] Handle seeing uncompressed sendgrid contact data
 (#35343)

---
 .../integration_tests/expected_records.jsonl  | 12 ++++-----
 .../connectors/source-sendgrid/metadata.yaml  |  2 +-
 .../connectors/source-sendgrid/pyproject.toml |  2 +-
 .../source_sendgrid/streams.py                |  8 +++++-
 .../source-sendgrid/unit_tests/unit_test.py   | 25 +++++++++++++++++--
 docs/integrations/sources/sendgrid.md         |  1 +
 6 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/airbyte-integrations/connectors/source-sendgrid/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-sendgrid/integration_tests/expected_records.jsonl
index 188db682c2c6..acf7830c5b8e 100644
--- a/airbyte-integrations/connectors/source-sendgrid/integration_tests/expected_records.jsonl
+++ b/airbyte-integrations/connectors/source-sendgrid/integration_tests/expected_records.jsonl
@@ -184,12 +184,12 @@
 {"stream": "suppression_group_members", "data": {"email": "test-forsuppressiongroup number8@example.com", "group_id": 14772, "group_name": "Test Suggestions Group 12", "created_at": 1612363238}, "emitted_at": 1631093393000}
 {"stream": "suppression_group_members", "data": {"email": "test-forsuppressiongroup number9@example.com", "group_id": 14772, "group_name": "Test Suggestions Group 12", "created_at": 1612363238}, "emitted_at": 1631093393000}
 {"stream": "suppression_group_members", "data": {"email": "avida.d3@gmail.com", "group_id": 14780, "group_name": "Test Suggestions Group 20", "created_at": 1631093329}, "emitted_at": 1631093393000}
-{"stream": "bounces", "data": { "created": 1621442821, "email": "vadym.hevlich@zazmicinvalid", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680684}
-{"stream": "bounces", "data": { "created": 1621441107, "email": "vadym.hevlich@zazmiccom2", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680684}
-{"stream": "bounces", "data": { "created": 1621442883, "email": "vadym.hevlich@zazmic_com", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680684}
-{"stream": "bounces", "data": { "created": 1621441104, "email": "vadym.hevlich@zazmiccom1", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680684}
-{"stream": "bounces", "data": { "created": 1621442811, "email": "vadym.hevlich@zazmicio", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680685}
-{"stream": "bounces", "data":  { "created": 1621430037, "email": "vadym.hevlich@zazmiccom", "reason": "Invalid Domain", "status": "" }, "emitted_at": 1678792680685}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmic_com", "created": 1621439283}, "emitted_at": 1708535996116}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmicinvalid", "created": 1621439221}, "emitted_at": 1708535996116}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmicio", "created": 1621439211}, "emitted_at": 1708535996116}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmiccom2", "created": 1621437507}, "emitted_at": 1708535996117}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmiccom1", "created": 1621437504}, "emitted_at": 1708535996117}
+{"stream": "bounces", "data": {"status": "", "reason": "Invalid Domain", "email": "vadym.hevlich@zazmiccom", "created": 1621426437}, "emitted_at": 1708535996117}
 {"stream": "campaigns", "data": {"created_at": "2021-09-08T09:07:48Z", "id": "3c5a9fa6-1084-11ec-ac32-4228d699bad5", "name": "Untitled Single Send", "status": "triggered", "updated_at": "2021-09-08T09:11:08Z", "is_abtest": false, "channels": ["email"]}, "emitted_at": 1678791750589}
 {"stream": "campaigns", "data": {"created_at": "2021-09-08T09:04:36Z", "id": "c9f286fb-1083-11ec-ae03-ca0fc7f28419", "name": "Copy of Untitled Single Send", "status": "triggered", "updated_at": "2021-09-08T09:09:08Z", "is_abtest": false, "channels": ["email"]}, "emitted_at": 1678791750589}
 {"stream": "campaigns", "data": {"created_at": "2021-09-08T08:53:59Z", "id": "4e5be6a3-1082-11ec-8512-9afd40c324e6", "name": "Untitled Single Send", "status": "triggered", "updated_at": "2021-09-08T08:57:08Z", "is_abtest": false, "channels": ["email"]}, "emitted_at": 1678791750590}
diff --git a/airbyte-integrations/connectors/source-sendgrid/metadata.yaml b/airbyte-integrations/connectors/source-sendgrid/metadata.yaml
index 607b8fc44d05..9955875b363d 100644
--- a/airbyte-integrations/connectors/source-sendgrid/metadata.yaml
+++ b/airbyte-integrations/connectors/source-sendgrid/metadata.yaml
@@ -10,7 +10,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87
-  dockerImageTag: 0.4.2
+  dockerImageTag: 0.4.3
   dockerRepository: airbyte/source-sendgrid
   documentationUrl: https://docs.airbyte.com/integrations/sources/sendgrid
   githubIssueLabel: source-sendgrid
diff --git a/airbyte-integrations/connectors/source-sendgrid/pyproject.toml b/airbyte-integrations/connectors/source-sendgrid/pyproject.toml
index 53ac7a8df890..35ad4315bcc9 100644
--- a/airbyte-integrations/connectors/source-sendgrid/pyproject.toml
+++ b/airbyte-integrations/connectors/source-sendgrid/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "0.4.2"
+version = "0.4.3"
 name = "source-sendgrid"
 description = "Source implementation for Sendgrid."
 authors = [ "Airbyte ",]
diff --git a/airbyte-integrations/connectors/source-sendgrid/source_sendgrid/streams.py b/airbyte-integrations/connectors/source-sendgrid/source_sendgrid/streams.py
index 9275048d660d..68f1932665cd 100644
--- a/airbyte-integrations/connectors/source-sendgrid/source_sendgrid/streams.py
+++ b/airbyte-integrations/connectors/source-sendgrid/source_sendgrid/streams.py
@@ -299,7 +299,13 @@ def download_data(self, url: str, chunk_size: int = 1024) -> tuple[str, str]:
             tmp_file, "wb"
         ) as data_file:
             for chunk in response.iter_content(chunk_size=chunk_size):
-                data_file.write(decompressor.decompress(chunk))
+                try:
+                    # see if it's compressed. we are seeing some that are not all of a sudden.
+                    # but let's also guard against the case where sendgrid changes it back.
+                    data_file.write(decompressor.decompress(chunk))
+                except zlib.error as e:
+                    # it's not actually compressed!
+                    data_file.write(chunk)
         # check the file exists
         if os.path.isfile(tmp_file):
             return tmp_file, self.encoding
diff --git a/airbyte-integrations/connectors/source-sendgrid/unit_tests/unit_test.py b/airbyte-integrations/connectors/source-sendgrid/unit_tests/unit_test.py
index 14fab1cb6bee..750a1db4c8b3 100644
--- a/airbyte-integrations/connectors/source-sendgrid/unit_tests/unit_test.py
+++ b/airbyte-integrations/connectors/source-sendgrid/unit_tests/unit_test.py
@@ -153,7 +153,7 @@ def test_should_retry_on_permission_error(requests_mock, stream_class, status, e
 
 def test_compressed_contact_response(requests_mock):
     stream = Contacts()
-    with open(os.path.dirname(__file__) + "/compressed_response", "rb") as compressed_response:
+    with open(os.path.dirname(__file__) + "/compressed_response", "rb") as file_response:
         url = "https://api.sendgrid.com/v3/marketing/contacts/exports"
         requests_mock.register_uri("POST", url, [{"json": {"id": "random_id"}, "status_code": 202}])
         url = "https://api.sendgrid.com/v3/marketing/contacts/exports/random_id"
@@ -162,7 +162,28 @@ def test_compressed_contact_response(requests_mock):
             {"json": {"status": "ready", "urls": ["https://sample_url/sample_csv.csv.gzip"]}, "status_code": 202},
         ]
         requests_mock.register_uri("GET", url, resp_bodies)
-        requests_mock.register_uri("GET", "https://sample_url/sample_csv.csv.gzip", [{"body": compressed_response, "status_code": 202}])
+        requests_mock.register_uri("GET", "https://sample_url/sample_csv.csv.gzip", [{"body": file_response, "status_code": 202}])
+        recs = list(stream.read_records(sync_mode=SyncMode.full_refresh))
+        decompressed_response = pd.read_csv(os.path.dirname(__file__) + "/decompressed_response.csv", dtype=str)
+        expected_records = [
+            {k.lower(): v for k, v in x.items()} for x in decompressed_response.replace({nan: None}).to_dict(orient="records")
+        ]
+
+        assert recs == expected_records
+
+
+def test_uncompressed_contact_response(requests_mock):
+    stream = Contacts()
+    with open(os.path.dirname(__file__) + "/decompressed_response.csv", "rb") as file_response:
+        url = "https://api.sendgrid.com/v3/marketing/contacts/exports"
+        requests_mock.register_uri("POST", url, [{"json": {"id": "random_id"}, "status_code": 202}])
+        url = "https://api.sendgrid.com/v3/marketing/contacts/exports/random_id"
+        resp_bodies = [
+            {"json": {"status": "pending", "id": "random_id", "urls": []}, "status_code": 202},
+            {"json": {"status": "ready", "urls": ["https://sample_url/sample_csv.csv.gzip"]}, "status_code": 202},
+        ]
+        requests_mock.register_uri("GET", url, resp_bodies)
+        requests_mock.register_uri("GET", "https://sample_url/sample_csv.csv.gzip", [{"body": file_response, "status_code": 202}])
         recs = list(stream.read_records(sync_mode=SyncMode.full_refresh))
         decompressed_response = pd.read_csv(os.path.dirname(__file__) + "/decompressed_response.csv", dtype=str)
         expected_records = [
diff --git a/docs/integrations/sources/sendgrid.md b/docs/integrations/sources/sendgrid.md
index a569b28ce89d..b3851579bbf2 100644
--- a/docs/integrations/sources/sendgrid.md
+++ b/docs/integrations/sources/sendgrid.md
@@ -84,6 +84,7 @@ The connector is restricted by normal Sendgrid [requests limitation](https://doc
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                                                                                                                                                           |
 |:--------|:-----------|:---------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.4.3 | 2024-02-21 | [35181](https://github.com/airbytehq/airbyte/pull/35343) | Handle uncompressed contacts downloads. |
 | 0.4.2 | 2024-02-12 | [35181](https://github.com/airbytehq/airbyte/pull/35181) | Manage dependencies with Poetry. |
 | 0.4.1 | 2023-10-18 | [31543](https://github.com/airbytehq/airbyte/pull/31543) | Base image migration: remove Dockerfile and use the python-connector-base image |
 | 0.4.0   | 2023-05-19 | [23959](https://github.com/airbytehq/airbyte/pull/23959) | Add `unsubscribe_groups`stream

From 6a746e63af4cde5cf0aec4cdf2214dad38d434fc Mon Sep 17 00:00:00 2001
From: Augustin 
Date: Thu, 22 Feb 2024 19:57:19 +0100
Subject: [PATCH 28/74] gradle.yml: use XXL runners but only if gradle related
 files are changed (#35548)

---
 .github/workflows/gradle.yml | 46 ++++++++++++++----------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index cc42ba2acbb4..9d9234b5a5ca 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -20,62 +20,52 @@ on:
       - synchronize
 
 jobs:
-  run-check:
-    # The gradle check task which we will run is embarrassingly parallelizable.
-    # We therefore run this on a machine with a maximum number of cores.
-    # We pay per time and per core, so there should be little difference in total cost.
-    # The latency overhead of setting up gradle prior to running the actual task adds up to about a minute.
-    runs-on: connector-test-large
-    name: Gradle Check
-    timeout-minutes: 30
+  changes:
+    runs-on: ubuntu-latest
     steps:
       - name: Checkout Airbyte
         uses: actions/checkout@v3
-      # IMPORTANT! This is necessary to make sure that a status is reported on the PR
-      # even if the workflow is skipped. If we used github actions filters, the workflow
-      # would not be reported as skipped, but instead would be forever pending.
-      #
-      # I KNOW THIS SOUNDS CRAZY, BUT IT IS TRUE.
-      #
-      # Also it gets worse
-      #
-      # IMPORTANT! DO NOT CHANGE THE QUOTES AROUND THE GLOBS. THEY ARE REQUIRED.
-      # MAKE SURE TO TEST ANY SYNTAX CHANGES BEFORE MERGING.
       - name: Get changed files
         uses: tj-actions/changed-files@v39
         id: changes
         with:
-          # Include java connectors and java CDK.
-          # Adding all *.java and *.gradle files gets us most of the way there.
-          # We're take a bit more strict for the java CDK, to make sure that
-          # the tests run when they should, for instance when changing the contents
-          # of a text file used as a resource.
           files_yaml: |
             gradlecheck:
               - '**/*.java'
               - '**/*.gradle'
               - 'airbyte-cdk/java/**/*'
+    outputs:
+      gradle: ${{ steps.changes.outputs.gradlecheck_any_changed }}
 
+  run-check:
+    needs:
+      - changes
+    if: needs.changes.outputs.gradle == 'true'
+    # The gradle check task which we will run is embarrassingly parallelizable.
+    # We therefore run this on a machine with a maximum number of cores.
+    # We pay per time and per core, so there should be little difference in total cost.
+    # The latency overhead of setting up gradle prior to running the actual task adds up to about a minute.
+    runs-on: connector-test-xxlarge
+    name: Gradle Check
+    timeout-minutes: 30
+    steps:
+      - name: Checkout Airbyte
+        uses: actions/checkout@v3
       - uses: actions/setup-java@v3
-        if: steps.changes.outputs.gradlecheck_any_changed == 'true'
         with:
           distribution: "zulu"
           java-version: "21"
       - name: Install Pip
-        if: steps.changes.outputs.gradlecheck_any_changed == 'true'
         run: curl -fsSL https://bootstrap.pypa.io/get-pip.py | python3
       - name: Install Pyenv
-        if: steps.changes.outputs.gradlecheck_any_changed == 'true'
         run: python3 -m pip install virtualenv --user
       - name: Docker login
-        if: steps.changes.outputs.gradlecheck_any_changed == 'true'
         # Some tests use testcontainers which pull images from DockerHub.
         uses: docker/login-action@v1
         with:
           username: ${{ secrets.DOCKER_HUB_USERNAME }}
           password: ${{ secrets.DOCKER_HUB_PASSWORD }}
       - name: Run Gradle Check
-        if: steps.changes.outputs.gradlecheck_any_changed == 'true'
         uses: burrunan/gradle-cache-action@v1
         env:
           CI: true

From 3e57e9822b526f9515e35e9560aad72ca0295567 Mon Sep 17 00:00:00 2001
From: Brian Lai <51336873+brianjlai@users.noreply.github.com>
Date: Thu, 22 Feb 2024 14:06:34 -0500
Subject: [PATCH 29/74] =?UTF-8?q?=E2=9C=A8=20[greenhouse]=20[iterable]=20[?=
 =?UTF-8?q?linkedin-ads]=20[paypal-transactions]=20[pinterest]=20Bump=20cd?=
 =?UTF-8?q?k=20versions=20for=20to=20use=20continue=20on=20stream=20per-er?=
 =?UTF-8?q?ror=20reporting=20(#35465)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../connectors/source-greenhouse/.coveragerc  |   3 +
 .../source-greenhouse/metadata.yaml           |   2 +-
 .../connectors/source-greenhouse/poetry.lock  | 183 ++++++------------
 .../source-greenhouse/pyproject.toml          |   4 +-
 .../unit_tests/test_streams.py                |   6 +-
 .../connectors/source-iterable/.coveragerc    |   3 +
 .../connectors/source-iterable/metadata.yaml  |   2 +-
 .../connectors/source-iterable/poetry.lock    |  28 +--
 .../connectors/source-iterable/pyproject.toml |   4 +-
 .../source-linkedin-ads/metadata.yaml         |   5 +-
 .../source-linkedin-ads/poetry.lock           |  36 ++--
 .../source-linkedin-ads/pyproject.toml        |   4 +-
 .../source-paypal-transaction/metadata.yaml   |   2 +-
 .../source-paypal-transaction/poetry.lock     |  41 ++--
 .../source-paypal-transaction/pyproject.toml  |   4 +-
 .../connectors/source-pinterest/.coveragerc   |   3 +
 .../integration_tests/expected_records.jsonl  |   2 +-
 .../connectors/source-pinterest/metadata.yaml |   2 +-
 .../connectors/source-pinterest/poetry.lock   |  38 ++--
 .../source-pinterest/pyproject.toml           |   4 +-
 docs/integrations/sources/greenhouse.md       |   3 +-
 docs/integrations/sources/iterable.md         |  59 +++---
 docs/integrations/sources/linkedin-ads.md     |   3 +-
 .../sources/paypal-transaction.md             |  13 +-
 docs/integrations/sources/pinterest.md        |   3 +-
 25 files changed, 203 insertions(+), 254 deletions(-)
 create mode 100644 airbyte-integrations/connectors/source-greenhouse/.coveragerc
 create mode 100644 airbyte-integrations/connectors/source-iterable/.coveragerc
 create mode 100644 airbyte-integrations/connectors/source-pinterest/.coveragerc

diff --git a/airbyte-integrations/connectors/source-greenhouse/.coveragerc b/airbyte-integrations/connectors/source-greenhouse/.coveragerc
new file mode 100644
index 000000000000..aceb412b78cd
--- /dev/null
+++ b/airbyte-integrations/connectors/source-greenhouse/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+omit =
+    source_greenhouse/run.py
\ No newline at end of file
diff --git a/airbyte-integrations/connectors/source-greenhouse/metadata.yaml b/airbyte-integrations/connectors/source-greenhouse/metadata.yaml
index 08cd46878e62..341baccb65ea 100644
--- a/airbyte-integrations/connectors/source-greenhouse/metadata.yaml
+++ b/airbyte-integrations/connectors/source-greenhouse/metadata.yaml
@@ -10,7 +10,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: 59f1e50a-331f-4f09-b3e8-2e8d4d355f44
-  dockerImageTag: 0.4.5
+  dockerImageTag: 0.5.0
   dockerRepository: airbyte/source-greenhouse
   documentationUrl: https://docs.airbyte.com/integrations/sources/greenhouse
   githubIssueLabel: source-greenhouse
diff --git a/airbyte-integrations/connectors/source-greenhouse/poetry.lock b/airbyte-integrations/connectors/source-greenhouse/poetry.lock
index 041631fa4dce..d00402201707 100644
--- a/airbyte-integrations/connectors/source-greenhouse/poetry.lock
+++ b/airbyte-integrations/connectors/source-greenhouse/poetry.lock
@@ -2,17 +2,17 @@
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.55.2"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.55.2.tar.gz", hash = "sha256:6b0d4db12505bf724811111851577960d98ba28019bd29ad51912885b86cab42"},
-    {file = "airbyte_cdk-0.55.2-py3-none-any.whl", hash = "sha256:af153a4ab3da54bb54ae5e7c1e6efa78ab5d76f038bd5ec3277948544b8b3212"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
-airbyte-protocol-models = "0.4.2"
+airbyte-protocol-models = "0.5.1"
 backoff = "*"
 cachetools = "*"
 Deprecated = ">=1.2,<2.0"
@@ -22,7 +22,7 @@ isodate = ">=0.6.1,<0.7.0"
 Jinja2 = ">=3.1.2,<3.2.0"
 jsonref = ">=0.2,<1.0"
 jsonschema = ">=3.2.0,<3.3.0"
-pendulum = "*"
+pendulum = "<3.0.0"
 pydantic = ">=1.10.8,<2.0.0"
 pyrate-limiter = ">=3.1.0,<3.2.0"
 python-dateutil = "*"
@@ -39,13 +39,13 @@ vector-db-based = ["cohere (==4.21)", "langchain (==0.0.271)", "openai[embedding
 
 [[package]]
 name = "airbyte-protocol-models"
-version = "0.4.2"
+version = "0.5.1"
 description = "Declares the Airbyte Protocol."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte_protocol_models-0.4.2-py3-none-any.whl", hash = "sha256:d3bbb14d4af9483bd7b08f5eb06f87e7113553bf4baed3998af95be873a0d821"},
-    {file = "airbyte_protocol_models-0.4.2.tar.gz", hash = "sha256:67b149d4812f8fdb88396b161274aa73cf0e16f22e35ce44f2bfc4d47e51915c"},
+    {file = "airbyte_protocol_models-0.5.1-py3-none-any.whl", hash = "sha256:dfe84e130e51ce2ae81a06d5aa36f6c5ce3152b9e36e6f0195fad6c3dab0927e"},
+    {file = "airbyte_protocol_models-0.5.1.tar.gz", hash = "sha256:7c8b16c7c1c7956b1996052e40585a3a93b1e44cb509c4e97c1ee4fe507ea086"},
 ]
 
 [package.dependencies]
@@ -497,102 +497,37 @@ files = [
 
 [[package]]
 name = "pendulum"
-version = "3.0.0"
+version = "2.1.2"
 description = "Python datetimes made easy"
 optional = false
-python-versions = ">=3.8"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 files = [
-    {file = "pendulum-3.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2cf9e53ef11668e07f73190c805dbdf07a1939c3298b78d5a9203a86775d1bfd"},
-    {file = "pendulum-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fb551b9b5e6059377889d2d878d940fd0bbb80ae4810543db18e6f77b02c5ef6"},
-    {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c58227ac260d5b01fc1025176d7b31858c9f62595737f350d22124a9a3ad82d"},
-    {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60fb6f415fea93a11c52578eaa10594568a6716602be8430b167eb0d730f3332"},
-    {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b69f6b4dbcb86f2c2fe696ba991e67347bcf87fe601362a1aba6431454b46bde"},
-    {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:138afa9c373ee450ede206db5a5e9004fd3011b3c6bbe1e57015395cd076a09f"},
-    {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:83d9031f39c6da9677164241fd0d37fbfc9dc8ade7043b5d6d62f56e81af8ad2"},
-    {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c2308af4033fa534f089595bcd40a95a39988ce4059ccd3dc6acb9ef14ca44a"},
-    {file = "pendulum-3.0.0-cp310-none-win_amd64.whl", hash = "sha256:9a59637cdb8462bdf2dbcb9d389518c0263799189d773ad5c11db6b13064fa79"},
-    {file = "pendulum-3.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3725245c0352c95d6ca297193192020d1b0c0f83d5ee6bb09964edc2b5a2d508"},
-    {file = "pendulum-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6c035f03a3e565ed132927e2c1b691de0dbf4eb53b02a5a3c5a97e1a64e17bec"},
-    {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597e66e63cbd68dd6d58ac46cb7a92363d2088d37ccde2dae4332ef23e95cd00"},
-    {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99a0f8172e19f3f0c0e4ace0ad1595134d5243cf75985dc2233e8f9e8de263ca"},
-    {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:77d8839e20f54706aed425bec82a83b4aec74db07f26acd039905d1237a5e1d4"},
-    {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde30e8146292b059020fbc8b6f8fd4a60ae7c5e6f0afef937bbb24880bdf01"},
-    {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:660434a6fcf6303c4efd36713ca9212c753140107ee169a3fc6c49c4711c2a05"},
-    {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dee9e5a48c6999dc1106eb7eea3e3a50e98a50651b72c08a87ee2154e544b33e"},
-    {file = "pendulum-3.0.0-cp311-none-win_amd64.whl", hash = "sha256:d4cdecde90aec2d67cebe4042fd2a87a4441cc02152ed7ed8fb3ebb110b94ec4"},
-    {file = "pendulum-3.0.0-cp311-none-win_arm64.whl", hash = "sha256:773c3bc4ddda2dda9f1b9d51fe06762f9200f3293d75c4660c19b2614b991d83"},
-    {file = "pendulum-3.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:409e64e41418c49f973d43a28afe5df1df4f1dd87c41c7c90f1a63f61ae0f1f7"},
-    {file = "pendulum-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a38ad2121c5ec7c4c190c7334e789c3b4624798859156b138fcc4d92295835dc"},
-    {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde4d0b2024b9785f66b7f30ed59281bd60d63d9213cda0eb0910ead777f6d37"},
-    {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2c5675769fb6d4c11238132962939b960fcb365436b6d623c5864287faa319"},
-    {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8af95e03e066826f0f4c65811cbee1b3123d4a45a1c3a2b4fc23c4b0dff893b5"},
-    {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2165a8f33cb15e06c67070b8afc87a62b85c5a273e3aaa6bc9d15c93a4920d6f"},
-    {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ad5e65b874b5e56bd942546ea7ba9dd1d6a25121db1c517700f1c9de91b28518"},
-    {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17fe4b2c844bbf5f0ece69cfd959fa02957c61317b2161763950d88fed8e13b9"},
-    {file = "pendulum-3.0.0-cp312-none-win_amd64.whl", hash = "sha256:78f8f4e7efe5066aca24a7a57511b9c2119f5c2b5eb81c46ff9222ce11e0a7a5"},
-    {file = "pendulum-3.0.0-cp312-none-win_arm64.whl", hash = "sha256:28f49d8d1e32aae9c284a90b6bb3873eee15ec6e1d9042edd611b22a94ac462f"},
-    {file = "pendulum-3.0.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d4e2512f4e1a4670284a153b214db9719eb5d14ac55ada5b76cbdb8c5c00399d"},
-    {file = "pendulum-3.0.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:3d897eb50883cc58d9b92f6405245f84b9286cd2de6e8694cb9ea5cb15195a32"},
-    {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e169cc2ca419517f397811bbe4589cf3cd13fca6dc38bb352ba15ea90739ebb"},
-    {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17c3084a4524ebefd9255513692f7e7360e23c8853dc6f10c64cc184e1217ab"},
-    {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826d6e258052715f64d05ae0fc9040c0151e6a87aae7c109ba9a0ed930ce4000"},
-    {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2aae97087872ef152a0c40e06100b3665d8cb86b59bc8471ca7c26132fccd0f"},
-    {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ac65eeec2250d03106b5e81284ad47f0d417ca299a45e89ccc69e36130ca8bc7"},
-    {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a5346d08f3f4a6e9e672187faa179c7bf9227897081d7121866358af369f44f9"},
-    {file = "pendulum-3.0.0-cp37-none-win_amd64.whl", hash = "sha256:235d64e87946d8f95c796af34818c76e0f88c94d624c268693c85b723b698aa9"},
-    {file = "pendulum-3.0.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:6a881d9c2a7f85bc9adafcfe671df5207f51f5715ae61f5d838b77a1356e8b7b"},
-    {file = "pendulum-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7762d2076b9b1cb718a6631ad6c16c23fc3fac76cbb8c454e81e80be98daa34"},
-    {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e8e36a8130819d97a479a0e7bf379b66b3b1b520e5dc46bd7eb14634338df8c"},
-    {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7dc843253ac373358ffc0711960e2dd5b94ab67530a3e204d85c6e8cb2c5fa10"},
-    {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a78ad3635d609ceb1e97d6aedef6a6a6f93433ddb2312888e668365908c7120"},
-    {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a137e9e0d1f751e60e67d11fc67781a572db76b2296f7b4d44554761049d6"},
-    {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c95984037987f4a457bb760455d9ca80467be792236b69d0084f228a8ada0162"},
-    {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d29c6e578fe0f893766c0d286adbf0b3c726a4e2341eba0917ec79c50274ec16"},
-    {file = "pendulum-3.0.0-cp38-none-win_amd64.whl", hash = "sha256:deaba8e16dbfcb3d7a6b5fabdd5a38b7c982809567479987b9c89572df62e027"},
-    {file = "pendulum-3.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b11aceea5b20b4b5382962b321dbc354af0defe35daa84e9ff3aae3c230df694"},
-    {file = "pendulum-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a90d4d504e82ad236afac9adca4d6a19e4865f717034fc69bafb112c320dcc8f"},
-    {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:825799c6b66e3734227756fa746cc34b3549c48693325b8b9f823cb7d21b19ac"},
-    {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad769e98dc07972e24afe0cff8d365cb6f0ebc7e65620aa1976fcfbcadc4c6f3"},
-    {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6fc26907eb5fb8cc6188cc620bc2075a6c534d981a2f045daa5f79dfe50d512"},
-    {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c717eab1b6d898c00a3e0fa7781d615b5c5136bbd40abe82be100bb06df7a56"},
-    {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3ddd1d66d1a714ce43acfe337190be055cdc221d911fc886d5a3aae28e14b76d"},
-    {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:822172853d7a9cf6da95d7b66a16c7160cb99ae6df55d44373888181d7a06edc"},
-    {file = "pendulum-3.0.0-cp39-none-win_amd64.whl", hash = "sha256:840de1b49cf1ec54c225a2a6f4f0784d50bd47f68e41dc005b7f67c7d5b5f3ae"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b1f74d1e6ffe5d01d6023870e2ce5c2191486928823196f8575dcc786e107b1"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:729e9f93756a2cdfa77d0fc82068346e9731c7e884097160603872686e570f07"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e586acc0b450cd21cbf0db6bae386237011b75260a3adceddc4be15334689a9a"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22e7944ffc1f0099a79ff468ee9630c73f8c7835cd76fdb57ef7320e6a409df4"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fa30af36bd8e50686846bdace37cf6707bdd044e5cb6e1109acbad3277232e04"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:440215347b11914ae707981b9a57ab9c7b6983ab0babde07063c6ee75c0dc6e7"},
-    {file = "pendulum-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:314c4038dc5e6a52991570f50edb2f08c339debdf8cea68ac355b32c4174e820"},
-    {file = "pendulum-3.0.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5acb1d386337415f74f4d1955c4ce8d0201978c162927d07df8eb0692b2d8533"},
-    {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a789e12fbdefaffb7b8ac67f9d8f22ba17a3050ceaaa635cd1cc4645773a4b1e"},
-    {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:860aa9b8a888e5913bd70d819306749e5eb488e6b99cd6c47beb701b22bdecf5"},
-    {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5ebc65ea033ef0281368217fbf59f5cb05b338ac4dd23d60959c7afcd79a60a0"},
-    {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9fef18ab0386ef6a9ac7bad7e43ded42c83ff7ad412f950633854f90d59afa8"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c134ba2f0571d0b68b83f6972e2307a55a5a849e7dac8505c715c531d2a8795"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:385680812e7e18af200bb9b4a49777418c32422d05ad5a8eb85144c4a285907b"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eec91cd87c59fb32ec49eb722f375bd58f4be790cae11c1b70fac3ee4f00da0"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4386bffeca23c4b69ad50a36211f75b35a4deb6210bdca112ac3043deb7e494a"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dfbcf1661d7146d7698da4b86e7f04814221081e9fe154183e34f4c5f5fa3bf8"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:04a1094a5aa1daa34a6b57c865b25f691848c61583fb22722a4df5699f6bf74c"},
-    {file = "pendulum-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5b0ec85b9045bd49dd3a3493a5e7ddfd31c36a2a60da387c419fa04abcaecb23"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0a15b90129765b705eb2039062a6daf4d22c4e28d1a54fa260892e8c3ae6e157"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:bb8f6d7acd67a67d6fedd361ad2958ff0539445ef51cbe8cd288db4306503cd0"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd69b15374bef7e4b4440612915315cc42e8575fcda2a3d7586a0d88192d0c88"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc00f8110db6898360c53c812872662e077eaf9c75515d53ecc65d886eec209a"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83a44e8b40655d0ba565a5c3d1365d27e3e6778ae2a05b69124db9e471255c4a"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1a3604e9fbc06b788041b2a8b78f75c243021e0f512447806a6d37ee5214905d"},
-    {file = "pendulum-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:92c307ae7accebd06cbae4729f0ba9fa724df5f7d91a0964b1b972a22baa482b"},
-    {file = "pendulum-3.0.0.tar.gz", hash = "sha256:5d034998dea404ec31fae27af6b22cff1708f830a1ed7353be4d1019bb9f584e"},
+    {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"},
+    {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"},
+    {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"},
+    {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"},
+    {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"},
+    {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"},
+    {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"},
+    {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"},
+    {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"},
+    {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"},
+    {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"},
+    {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"},
+    {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"},
+    {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"},
+    {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"},
+    {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"},
+    {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"},
+    {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"},
+    {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"},
+    {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"},
+    {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"},
 ]
 
 [package.dependencies]
-python-dateutil = ">=2.6"
-tzdata = ">=2020.1"
-
-[package.extras]
-test = ["time-machine (>=2.6.0)"]
+python-dateutil = ">=2.6,<3.0"
+pytzdata = ">=2020.1"
 
 [[package]]
 name = "platformdirs"
@@ -798,6 +733,17 @@ files = [
 [package.dependencies]
 six = ">=1.5"
 
+[[package]]
+name = "pytzdata"
+version = "2020.1"
+description = "The Olson timezone database for Python."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+    {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"},
+    {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"},
+]
+
 [[package]]
 name = "pyyaml"
 version = "6.0.1"
@@ -881,13 +827,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "requests-cache"
-version = "1.1.1"
+version = "1.2.0"
 description = "A persistent cache for python requests"
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8"
 files = [
-    {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"},
-    {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"},
+    {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
+    {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
 ]
 
 [package.dependencies]
@@ -899,15 +845,15 @@ url-normalize = ">=1.4"
 urllib3 = ">=1.25.5"
 
 [package.extras]
-all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"]
+all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
 bson = ["bson (>=0.5)"]
-docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"]
+docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
 dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
 json = ["ujson (>=5.4)"]
 mongodb = ["pymongo (>=3)"]
 redis = ["redis (>=3)"]
 security = ["itsdangerous (>=2.0)"]
-yaml = ["pyyaml (>=5.4)"]
+yaml = ["pyyaml (>=6.0.1)"]
 
 [[package]]
 name = "requests-mock"
@@ -930,18 +876,18 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes
 
 [[package]]
 name = "setuptools"
-version = "69.0.3"
+version = "69.1.0"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
-    {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
+    {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"},
+    {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"},
 ]
 
 [package.extras]
 docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
 testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
 
 [[package]]
@@ -977,17 +923,6 @@ files = [
     {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
 ]
 
-[[package]]
-name = "tzdata"
-version = "2023.4"
-description = "Provider of IANA time zone data"
-optional = false
-python-versions = ">=2"
-files = [
-    {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
-    {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
-]
-
 [[package]]
 name = "url-normalize"
 version = "1.4.3"
@@ -1004,13 +939,13 @@ six = "*"
 
 [[package]]
 name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
-    {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+    {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+    {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
 ]
 
 [package.extras]
@@ -1115,4 +1050,4 @@ files = [
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "506fae69a7cb311ffdf66430bf0acc0ece521c351cb6049bb15088c46ac7b055"
+content-hash = "ad41b784b46cb6a10f61c59bcdea7023d6326bd7d735a29e673ac23cf4ef9e0e"
diff --git a/airbyte-integrations/connectors/source-greenhouse/pyproject.toml b/airbyte-integrations/connectors/source-greenhouse/pyproject.toml
index 0f47f6772314..2da2664aef98 100644
--- a/airbyte-integrations/connectors/source-greenhouse/pyproject.toml
+++ b/airbyte-integrations/connectors/source-greenhouse/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "0.4.5"
+version = "0.5.0"
 name = "source-greenhouse"
 description = "Source implementation for Greenhouse."
 authors = [ "Airbyte ",]
@@ -17,7 +17,7 @@ include = "source_greenhouse"
 
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
-airbyte-cdk = "==0.55.2"
+airbyte-cdk = "==0.63.2"
 dataclasses-jsonschema = "==2.15.1"
 
 [tool.poetry.scripts]
diff --git a/airbyte-integrations/connectors/source-greenhouse/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-greenhouse/unit_tests/test_streams.py
index a7a9adaf7202..3adfc4cb9efc 100644
--- a/airbyte-integrations/connectors/source-greenhouse/unit_tests/test_streams.py
+++ b/airbyte-integrations/connectors/source-greenhouse/unit_tests/test_streams.py
@@ -138,7 +138,7 @@ def test_parse_response_expected_response(applications_stream):
         ]
     """
     response._content = response_content
-    parsed_response = applications_stream.retriever._parse_response(response, stream_state={})
+    parsed_response = applications_stream.retriever._parse_response(response, stream_state={}, records_schema={})
     records = [dict(record) for record in parsed_response]
 
     assert records == json.loads(response_content)
@@ -148,7 +148,7 @@ def test_parse_response_empty_content(applications_stream):
     response = requests.Response()
     response.status_code = 200
     response._content = b"[]"
-    parsed_response = applications_stream.retriever._parse_response(response, stream_state={})
+    parsed_response = applications_stream.retriever._parse_response(response, stream_state={}, records_schema={})
     records = [record for record in parsed_response]
 
     assert records == []
@@ -164,7 +164,7 @@ def test_ignore_403(applications_stream):
     response = requests.Response()
     response.status_code = 403
     response._content = b""
-    parsed_response = applications_stream.retriever._parse_response(response, stream_state={})
+    parsed_response = applications_stream.retriever._parse_response(response, stream_state={}, records_schema={})
     records = [record for record in parsed_response]
     assert records == []
 
diff --git a/airbyte-integrations/connectors/source-iterable/.coveragerc b/airbyte-integrations/connectors/source-iterable/.coveragerc
new file mode 100644
index 000000000000..abcf74bbab2f
--- /dev/null
+++ b/airbyte-integrations/connectors/source-iterable/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+omit =
+    source_iterable/run.py
\ No newline at end of file
diff --git a/airbyte-integrations/connectors/source-iterable/metadata.yaml b/airbyte-integrations/connectors/source-iterable/metadata.yaml
index 9c4a5be39fb2..ce432b88e86e 100644
--- a/airbyte-integrations/connectors/source-iterable/metadata.yaml
+++ b/airbyte-integrations/connectors/source-iterable/metadata.yaml
@@ -10,7 +10,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: 2e875208-0c0b-4ee4-9e92-1cb3156ea799
-  dockerImageTag: 0.2.2
+  dockerImageTag: 0.3.0
   dockerRepository: airbyte/source-iterable
   documentationUrl: https://docs.airbyte.com/integrations/sources/iterable
   githubIssueLabel: source-iterable
diff --git a/airbyte-integrations/connectors/source-iterable/poetry.lock b/airbyte-integrations/connectors/source-iterable/poetry.lock
index 5df7797ca922..03b1a7d4555c 100644
--- a/airbyte-integrations/connectors/source-iterable/poetry.lock
+++ b/airbyte-integrations/connectors/source-iterable/poetry.lock
@@ -2,13 +2,13 @@
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.58.8"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.58.8.tar.gz", hash = "sha256:80cfad673302802e0f5d485879f1bd2f3679a4e3b12b2af42bd7bb37a3991a71"},
-    {file = "airbyte_cdk-0.58.8-py3-none-any.whl", hash = "sha256:5b0b19745e96ba3f20683c48530d58a00be48361dfa34ec3c38cef8da03ba330"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
@@ -822,13 +822,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "requests-cache"
-version = "1.1.1"
+version = "1.2.0"
 description = "A persistent cache for python requests"
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8"
 files = [
-    {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"},
-    {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"},
+    {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
+    {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
 ]
 
 [package.dependencies]
@@ -840,15 +840,15 @@ url-normalize = ">=1.4"
 urllib3 = ">=1.25.5"
 
 [package.extras]
-all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"]
+all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
 bson = ["bson (>=0.5)"]
-docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"]
+docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
 dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
 json = ["ujson (>=5.4)"]
 mongodb = ["pymongo (>=3)"]
 redis = ["redis (>=3)"]
 security = ["itsdangerous (>=2.0)"]
-yaml = ["pyyaml (>=5.4)"]
+yaml = ["pyyaml (>=6.0.1)"]
 
 [[package]]
 name = "requests-mock"
@@ -965,13 +965,13 @@ six = "*"
 
 [[package]]
 name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
-    {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+    {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+    {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
 ]
 
 [package.extras]
@@ -1076,4 +1076,4 @@ files = [
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "f1945b892387cf72be4b68c0c5d98397c8f22db065b6b79312b75d84eff5e432"
+content-hash = "21991266470e2efceb259f4d42e1cdc62654126c7ed975ac9e0cbaf43f588347"
diff --git a/airbyte-integrations/connectors/source-iterable/pyproject.toml b/airbyte-integrations/connectors/source-iterable/pyproject.toml
index ad0c6ba8967b..9c92df926217 100644
--- a/airbyte-integrations/connectors/source-iterable/pyproject.toml
+++ b/airbyte-integrations/connectors/source-iterable/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "0.2.2"
+version = "0.3.0"
 name = "source-iterable"
 description = "Source implementation for Iterable."
 authors = [ "Airbyte ",]
@@ -18,7 +18,7 @@ include = "source_iterable"
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
 pendulum = "==2.1.2"
-airbyte-cdk = "==0.58.8"
+airbyte-cdk = "==0.63.2"
 requests = "==2.31.0"
 python-dateutil = "==2.8.2"
 
diff --git a/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml b/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml
index 6ac094731c53..e7a9a9212eb0 100644
--- a/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml
+++ b/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml
@@ -11,7 +11,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: 137ece28-5434-455c-8f34-69dc3782f451
-  dockerImageTag: 0.6.8
+  dockerImageTag: 0.7.0
   dockerRepository: airbyte/source-linkedin-ads
   documentationUrl: https://docs.airbyte.com/integrations/sources/linkedin-ads
   githubIssueLabel: source-linkedin-ads
@@ -21,8 +21,7 @@ data:
   name: LinkedIn Ads
   remoteRegistries:
     pypi:
-      enabled: false
-      # TODO: Set enabled=true after `airbyte-lib-validate-source` is passing.
+      enabled: true
       packageName: airbyte-source-linkedin-ads
   registries:
     cloud:
diff --git a/airbyte-integrations/connectors/source-linkedin-ads/poetry.lock b/airbyte-integrations/connectors/source-linkedin-ads/poetry.lock
index 117c14fb5a2d..4c1cbe822ae2 100644
--- a/airbyte-integrations/connectors/source-linkedin-ads/poetry.lock
+++ b/airbyte-integrations/connectors/source-linkedin-ads/poetry.lock
@@ -2,13 +2,13 @@
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.58.8"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.58.8.tar.gz", hash = "sha256:80cfad673302802e0f5d485879f1bd2f3679a4e3b12b2af42bd7bb37a3991a71"},
-    {file = "airbyte_cdk-0.58.8-py3-none-any.whl", hash = "sha256:5b0b19745e96ba3f20683c48530d58a00be48361dfa34ec3c38cef8da03ba330"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
@@ -808,13 +808,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "requests-cache"
-version = "1.1.1"
+version = "1.2.0"
 description = "A persistent cache for python requests"
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8"
 files = [
-    {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"},
-    {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"},
+    {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
+    {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
 ]
 
 [package.dependencies]
@@ -826,15 +826,15 @@ url-normalize = ">=1.4"
 urllib3 = ">=1.25.5"
 
 [package.extras]
-all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"]
+all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
 bson = ["bson (>=0.5)"]
-docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"]
+docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
 dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
 json = ["ujson (>=5.4)"]
 mongodb = ["pymongo (>=3)"]
 redis = ["redis (>=3)"]
 security = ["itsdangerous (>=2.0)"]
-yaml = ["pyyaml (>=5.4)"]
+yaml = ["pyyaml (>=6.0.1)"]
 
 [[package]]
 name = "requests-mock"
@@ -857,18 +857,18 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes
 
 [[package]]
 name = "setuptools"
-version = "69.0.3"
+version = "69.1.0"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
-    {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
+    {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"},
+    {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"},
 ]
 
 [package.extras]
 docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
 testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
 
 [[package]]
@@ -920,13 +920,13 @@ six = "*"
 
 [[package]]
 name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
-    {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+    {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+    {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
 ]
 
 [package.extras]
@@ -1031,4 +1031,4 @@ files = [
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "ecd30b56ee2c9583b83adf339dde18884725acda2e6803afb684290e79c6fd14"
+content-hash = "861d01a7b883a61e01367a1c883fbc1699ef39984c364c6bd9984703c1747375"
diff --git a/airbyte-integrations/connectors/source-linkedin-ads/pyproject.toml b/airbyte-integrations/connectors/source-linkedin-ads/pyproject.toml
index dce2cbf6c9f6..bcbb55b92573 100644
--- a/airbyte-integrations/connectors/source-linkedin-ads/pyproject.toml
+++ b/airbyte-integrations/connectors/source-linkedin-ads/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "0.6.8"
+version = "0.7.0"
 name = "source-linkedin-ads"
 description = "Source implementation for Linkedin Ads."
 authors = [ "Airbyte ",]
@@ -17,7 +17,7 @@ include = "source_linkedin_ads"
 
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
-airbyte-cdk = "==0.58.8"
+airbyte-cdk = "==0.63.2"
 
 [tool.poetry.scripts]
 source-linkedin-ads = "source_linkedin_ads.run:run"
diff --git a/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml b/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml
index 3449c818497c..a1974a83fbe7 100644
--- a/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml
+++ b/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml
@@ -11,7 +11,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: d913b0f2-cc51-4e55-a44c-8ba1697b9239
-  dockerImageTag: 2.3.0
+  dockerImageTag: 2.4.0
   dockerRepository: airbyte/source-paypal-transaction
   documentationUrl: https://docs.airbyte.com/integrations/sources/paypal-transaction
   githubIssueLabel: source-paypal-transaction
diff --git a/airbyte-integrations/connectors/source-paypal-transaction/poetry.lock b/airbyte-integrations/connectors/source-paypal-transaction/poetry.lock
index 421031229419..4200fc8953a1 100644
--- a/airbyte-integrations/connectors/source-paypal-transaction/poetry.lock
+++ b/airbyte-integrations/connectors/source-paypal-transaction/poetry.lock
@@ -2,13 +2,13 @@
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.62.0"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.62.0.tar.gz", hash = "sha256:622f56bd7101493a74f11c33a45a31c251032333989996f137cac8370873c614"},
-    {file = "airbyte_cdk-0.62.0-py3-none-any.whl", hash = "sha256:b21330a566b33dbdddde33243eb9855f086ad4272e3585ca626be1225451a3b8"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
@@ -752,13 +752,13 @@ files = [
 
 [[package]]
 name = "pytest"
-version = "8.0.0"
+version = "8.0.1"
 description = "pytest: simple powerful testing with Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"},
-    {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"},
+    {file = "pytest-8.0.1-py3-none-any.whl", hash = "sha256:3e4f16fe1c0a9dc9d9389161c127c3edc5d810c38d6793042fb81d9f48a59fca"},
+    {file = "pytest-8.0.1.tar.gz", hash = "sha256:267f6563751877d772019b13aacbe4e860d73fe8f651f28112e9ac37de7513ae"},
 ]
 
 [package.dependencies]
@@ -839,6 +839,7 @@ files = [
     {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
     {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
     {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+    {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
     {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
     {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
     {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@@ -896,13 +897,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "requests-cache"
-version = "1.1.1"
+version = "1.2.0"
 description = "A persistent cache for python requests"
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8"
 files = [
-    {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"},
-    {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"},
+    {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
+    {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
 ]
 
 [package.dependencies]
@@ -914,15 +915,15 @@ url-normalize = ">=1.4"
 urllib3 = ">=1.25.5"
 
 [package.extras]
-all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"]
+all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
 bson = ["bson (>=0.5)"]
-docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"]
+docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
 dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
 json = ["ujson (>=5.4)"]
 mongodb = ["pymongo (>=3)"]
 redis = ["redis (>=3)"]
 security = ["itsdangerous (>=2.0)"]
-yaml = ["pyyaml (>=5.4)"]
+yaml = ["pyyaml (>=6.0.1)"]
 
 [[package]]
 name = "requests-mock"
@@ -945,13 +946,13 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes
 
 [[package]]
 name = "selenium"
-version = "4.17.2"
+version = "4.18.1"
 description = ""
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "selenium-4.17.2-py3-none-any.whl", hash = "sha256:5aee79026c07985dc1b0c909f34084aa996dfe5b307602de9016d7a621a473f2"},
-    {file = "selenium-4.17.2.tar.gz", hash = "sha256:d43d6972e516855fb242ef9ce4ce759057b115070e702e7b1c1032fe7b38d87b"},
+    {file = "selenium-4.18.1-py3-none-any.whl", hash = "sha256:b24a3cdd2d47c29832e81345bfcde0c12bb608738013e53c781b211b418df241"},
+    {file = "selenium-4.18.1.tar.gz", hash = "sha256:a11f67afa8bfac6b77e148c987b33f6b14eb1cae4d352722a75de1f26e3f0ae2"},
 ]
 
 [package.dependencies]
@@ -1084,13 +1085,13 @@ six = "*"
 
 [[package]]
 name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
-    {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+    {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+    {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
 ]
 
 [package.dependencies]
@@ -1212,4 +1213,4 @@ h11 = ">=0.9.0,<1"
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "734a63a70fbb15f2bba2328a4f124785e30c369ad58062eb68afc53df56a5ef0"
+content-hash = "3e201a0e17ac40faf9a73f3e2b9e924e0d3993ee8982646436ea6517f8f6cd7b"
diff --git a/airbyte-integrations/connectors/source-paypal-transaction/pyproject.toml b/airbyte-integrations/connectors/source-paypal-transaction/pyproject.toml
index 00533e610e8a..36ea7e8161e9 100644
--- a/airbyte-integrations/connectors/source-paypal-transaction/pyproject.toml
+++ b/airbyte-integrations/connectors/source-paypal-transaction/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "2.3.0"
+version = "2.4.0"
 name = "source-paypal-transaction"
 description = "Source implementation for Paypal Transaction."
 authors = [ "Airbyte ",]
@@ -17,7 +17,7 @@ include = "source_paypal_transaction"
 
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
-airbyte-cdk = "==0.62.0"
+airbyte-cdk = "==0.63.2"
 
 
 [tool.poetry.scripts]
diff --git a/airbyte-integrations/connectors/source-pinterest/.coveragerc b/airbyte-integrations/connectors/source-pinterest/.coveragerc
new file mode 100644
index 000000000000..a0c6e7c485cb
--- /dev/null
+++ b/airbyte-integrations/connectors/source-pinterest/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+omit =
+    source_pinterest/run.py
\ No newline at end of file
diff --git a/airbyte-integrations/connectors/source-pinterest/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-pinterest/integration_tests/expected_records.jsonl
index 5291284dcf14..010cf0912179 100644
--- a/airbyte-integrations/connectors/source-pinterest/integration_tests/expected_records.jsonl
+++ b/airbyte-integrations/connectors/source-pinterest/integration_tests/expected_records.jsonl
@@ -12,7 +12,7 @@
 {"stream": "campaign_analytics", "data": {"TOTAL_IMPRESSION_FREQUENCY": 1.0, "CAMPAIGN_LIFETIME_SPEND_CAP": 0.0, "TOTAL_IMPRESSION_USER": 1.0, "CAMPAIGN_ENTITY_STATUS": 1.0, "CAMPAIGN_DAILY_SPEND_CAP": 25000000.0, "ADVERTISER_ID": 549761668032.0, "DATE": "2023-12-04", "IMPRESSION_2": 1.0, "AD_ACCOUNT_ID": "549761668032", "CAMPAIGN_ID": 626744128982.0, "CAMPAIGN_NAME": "2021-06-08 09:08 UTC | Brand awareness"}, "emitted_at": 1708094774057}
 {"stream": "campaign_analytics_report", "data": {"ADVERTISER_ID": 549761668032.0, "AD_ACCOUNT_ID": "549761668032", "CAMPAIGN_DAILY_SPEND_CAP": 25000000.0, "CAMPAIGN_ENTITY_STATUS": "ACTIVE", "CAMPAIGN_ID": 626744128982.0, "CAMPAIGN_LIFETIME_SPEND_CAP": 0.0, "CAMPAIGN_NAME": "2021-06-08 09:08 UTC | Brand awareness", "IMPRESSION_2": 3.0, "TOTAL_IMPRESSION_FREQUENCY": 1.5, "TOTAL_IMPRESSION_USER": 2.0, "DATE": "2023-07-14"}, "emitted_at": 1690299367301}
 {"stream": "campaign_targeting_report", "data": {"ADVERTISER_ID": 549761668032.0, "AD_ACCOUNT_ID": "549761668032", "CAMPAIGN_DAILY_SPEND_CAP": 25000000.0, "CAMPAIGN_ENTITY_STATUS": "ACTIVE", "CAMPAIGN_ID": 626744128982.0, "CAMPAIGN_LIFETIME_SPEND_CAP": 0.0, "CAMPAIGN_NAME": "2021-06-08 09:08 UTC | Brand awareness", "IMPRESSION_2": 1.0, "TARGETING_VALUE": "TWOCOLUMN_FEED", "TARGETING_TYPE": "FEED_TYPE", "DATE": "2023-10-29"}, "emitted_at": 1699894287823}
-{"stream": "user_account_analytics", "data": {"date": "2023-11-19", "data_status": "READY", "metrics": {"VIDEO_V50_WATCH_TIME": 0, "PIN_CLICK_RATE": 0.02092050209205021, "OUTBOUND_CLICK_RATE": 0.0, "ENGAGEMENT_RATE": 0.02510460251046025, "IMPRESSION": 239.0, "SAVE_RATE": 0.0041841004184100415, "VIDEO_AVG_WATCH_TIME": 0.0, "SAVE": 1.0, "PIN_CLICK": 5, "QUARTILE_95_PERCENT_VIEW": 0, "OUTBOUND_CLICK": 0, "VIDEO_10S_VIEW": 0, "VIDEO_MRC_VIEW": 0, "ENGAGEMENT": 6.0, "VIDEO_START": 0}}, "emitted_at": 1708094826279}
+{"stream": "user_account_analytics", "data": {"date": "2024-02-18", "data_status": "READY", "metrics": {"SAVE": 6.0, "VIDEO_MRC_VIEW": 0, "VIDEO_10S_VIEW": 0, "PIN_CLICK": 15, "OUTBOUND_CLICK_RATE": 0.0017123287671232876, "QUARTILE_95_PERCENT_VIEW": 0, "ENGAGEMENT_RATE": 0.03767123287671233, "VIDEO_START": 0, "IMPRESSION": 584.0, "OUTBOUND_CLICK": 1, "ENGAGEMENT": 22.0, "PIN_CLICK_RATE": 0.025684931506849314, "VIDEO_V50_WATCH_TIME": 0, "SAVE_RATE": 0.010273972602739725, "VIDEO_AVG_WATCH_TIME": 0.0}}, "emitted_at": 1708476886035}
 {"stream": "keywords", "data": {"archived": false, "id": "2886935172273", "parent_id": "2680068678965", "parent_type": "AD_GROUP", "type": "KEYWORD", "bid": null, "match_type": "BROAD", "value": "data science"}, "emitted_at": 1699393669235}
 {"stream": "audiences", "data": {"type": "audience", "id": "2542622254639", "name": "airbyte audience", "ad_account_id": "549761668032", "audience_type": "ENGAGEMENT", "description": "airbyte audience", "status": "TOO_SMALL", "rule": {"engager_type": 1}}, "emitted_at": 1699293090886}
 {"stream": "advertiser_report", "data": {"ADVERTISER_ID": 549761668032.0, "AD_ACCOUNT_ID": "549761668032", "EENGAGEMENT_RATE": 0.1, "ENGAGEMENT_2": 1.0, "IMPRESSION_2": 10.0, "REPIN_2": 1.0, "TOTAL_ENGAGEMENT": 1.0, "TOTAL_IMPRESSION_FREQUENCY": 5.0, "TOTAL_IMPRESSION_USER": 2.0, "TOTAL_REPIN_RATE": 0.1, "DATE": "2023-02-10"}, "emitted_at": 1699894848024}
diff --git a/airbyte-integrations/connectors/source-pinterest/metadata.yaml b/airbyte-integrations/connectors/source-pinterest/metadata.yaml
index 10aaf931d8a9..e541750bdf51 100644
--- a/airbyte-integrations/connectors/source-pinterest/metadata.yaml
+++ b/airbyte-integrations/connectors/source-pinterest/metadata.yaml
@@ -5,7 +5,7 @@ data:
   connectorSubtype: api
   connectorType: source
   definitionId: 5cb7e5fe-38c2-11ec-8d3d-0242ac130003
-  dockerImageTag: 1.1.1
+  dockerImageTag: 1.2.0
   dockerRepository: airbyte/source-pinterest
   connectorBuildOptions:
     baseImage: docker.io/airbyte/python-connector-base:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c
diff --git a/airbyte-integrations/connectors/source-pinterest/poetry.lock b/airbyte-integrations/connectors/source-pinterest/poetry.lock
index 95f345b2b5c5..f3f3fee593a6 100644
--- a/airbyte-integrations/connectors/source-pinterest/poetry.lock
+++ b/airbyte-integrations/connectors/source-pinterest/poetry.lock
@@ -2,17 +2,17 @@
 
 [[package]]
 name = "airbyte-cdk"
-version = "0.53.9"
+version = "0.63.2"
 description = "A framework for writing Airbyte Connectors."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte-cdk-0.53.9.tar.gz", hash = "sha256:22251a4306b516fa5665e79d4db25203cd6a95cc95d23f3e712ec89e0995e7f0"},
-    {file = "airbyte_cdk-0.53.9-py3-none-any.whl", hash = "sha256:0730e33bfde63a817fa5fc9115c22c6ba847e73fcf1a7c955e33840942394386"},
+    {file = "airbyte-cdk-0.63.2.tar.gz", hash = "sha256:b2edc160f560352a816f3a266b5dfa6dfe37868add1e3a0a2628eb19ba771ed1"},
+    {file = "airbyte_cdk-0.63.2-py3-none-any.whl", hash = "sha256:8698cb94514f35577123520954503cb2da407423af109dffd03644ba8b0093cd"},
 ]
 
 [package.dependencies]
-airbyte-protocol-models = "0.4.2"
+airbyte-protocol-models = "0.5.1"
 backoff = "*"
 cachetools = "*"
 Deprecated = ">=1.2,<2.0"
@@ -22,7 +22,7 @@ isodate = ">=0.6.1,<0.7.0"
 Jinja2 = ">=3.1.2,<3.2.0"
 jsonref = ">=0.2,<1.0"
 jsonschema = ">=3.2.0,<3.3.0"
-pendulum = "*"
+pendulum = "<3.0.0"
 pydantic = ">=1.10.8,<2.0.0"
 pyrate-limiter = ">=3.1.0,<3.2.0"
 python-dateutil = "*"
@@ -39,13 +39,13 @@ vector-db-based = ["cohere (==4.21)", "langchain (==0.0.271)", "openai[embedding
 
 [[package]]
 name = "airbyte-protocol-models"
-version = "0.4.2"
+version = "0.5.1"
 description = "Declares the Airbyte Protocol."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "airbyte_protocol_models-0.4.2-py3-none-any.whl", hash = "sha256:d3bbb14d4af9483bd7b08f5eb06f87e7113553bf4baed3998af95be873a0d821"},
-    {file = "airbyte_protocol_models-0.4.2.tar.gz", hash = "sha256:67b149d4812f8fdb88396b161274aa73cf0e16f22e35ce44f2bfc4d47e51915c"},
+    {file = "airbyte_protocol_models-0.5.1-py3-none-any.whl", hash = "sha256:dfe84e130e51ce2ae81a06d5aa36f6c5ce3152b9e36e6f0195fad6c3dab0927e"},
+    {file = "airbyte_protocol_models-0.5.1.tar.gz", hash = "sha256:7c8b16c7c1c7956b1996052e40585a3a93b1e44cb509c4e97c1ee4fe507ea086"},
 ]
 
 [package.dependencies]
@@ -808,13 +808,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "requests-cache"
-version = "1.1.1"
+version = "1.2.0"
 description = "A persistent cache for python requests"
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8"
 files = [
-    {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"},
-    {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"},
+    {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
+    {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
 ]
 
 [package.dependencies]
@@ -826,15 +826,15 @@ url-normalize = ">=1.4"
 urllib3 = ">=1.25.5"
 
 [package.extras]
-all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"]
+all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
 bson = ["bson (>=0.5)"]
-docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"]
+docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
 dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
 json = ["ujson (>=5.4)"]
 mongodb = ["pymongo (>=3)"]
 redis = ["redis (>=3)"]
 security = ["itsdangerous (>=2.0)"]
-yaml = ["pyyaml (>=5.4)"]
+yaml = ["pyyaml (>=6.0.1)"]
 
 [[package]]
 name = "requests-mock"
@@ -939,13 +939,13 @@ six = "*"
 
 [[package]]
 name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
 description = "HTTP library with thread-safe connection pooling, file post, and more."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
-    {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+    {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+    {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
 ]
 
 [package.extras]
@@ -1050,4 +1050,4 @@ files = [
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.9,<3.12"
-content-hash = "01f0e9a1bc8ef6c022c261ef26e7902b999fd72c9bb233793438b719ce9f22f7"
+content-hash = "07657dff3674cca2f376658bfa717048c9caff7fa3b6f23144133f1d6dbac33a"
diff --git a/airbyte-integrations/connectors/source-pinterest/pyproject.toml b/airbyte-integrations/connectors/source-pinterest/pyproject.toml
index c3a901aa0089..486999671d09 100644
--- a/airbyte-integrations/connectors/source-pinterest/pyproject.toml
+++ b/airbyte-integrations/connectors/source-pinterest/pyproject.toml
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
 build-backend = "poetry.core.masonry.api"
 
 [tool.poetry]
-version = "1.1.1"
+version = "1.2.0"
 name = "source-pinterest"
 description = "Source implementation for Pinterest."
 authors = [ "Airbyte ",]
@@ -18,7 +18,7 @@ include = "source_pinterest"
 [tool.poetry.dependencies]
 python = "^3.9,<3.12"
 pendulum = "==2.1.2"
-airbyte-cdk = "==0.53.9"
+airbyte-cdk = "==0.63.2"
 
 [tool.poetry.scripts]
 source-pinterest = "source_pinterest.run:run"
diff --git a/docs/integrations/sources/greenhouse.md b/docs/integrations/sources/greenhouse.md
index 90ff7c1b3ebb..05b270d34d2e 100644
--- a/docs/integrations/sources/greenhouse.md
+++ b/docs/integrations/sources/greenhouse.md
@@ -63,7 +63,8 @@ The Greenhouse connector should not run into Greenhouse API limitations under no
 ## Changelog
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                                                                              |
-| :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:--------|:-----------|:---------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.5.0   | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures                                                                                                             |
 | 0.4.5   | 2024-02-09 | [35077](https://github.com/airbytehq/airbyte/pull/35077) | Manage dependencies with Poetry.                                                                                                                                     |
 | 0.4.4   | 2023-11-29 | [32397](https://github.com/airbytehq/airbyte/pull/32397) | Increase test coverage and migrate to base image                                                                                                                     |
 | 0.4.3   | 2023-09-20 | [30648](https://github.com/airbytehq/airbyte/pull/30648) | Update candidates.json                                                                                                                                               |
diff --git a/docs/integrations/sources/iterable.md b/docs/integrations/sources/iterable.md
index db857ed3cee6..ce4b7d200967 100644
--- a/docs/integrations/sources/iterable.md
+++ b/docs/integrations/sources/iterable.md
@@ -78,33 +78,34 @@ The Iterable source connector supports the following [sync modes](https://docs.a
 
 ## Changelog
 
-| Version | Date       | Pull Request                                             | Subject                                                                                                      |
-| :------ | :--------- | :------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
-| 0.2.2 | 2024-02-12 | [35150](https://github.com/airbytehq/airbyte/pull/35150) | Manage dependencies with Poetry. |
-| 0.2.1   | 2024-01-12 | [1234](https://github.com/airbytehq/airbyte/pull/1234) | prepare for airbyte-lib                                                        |
+| Version | Date       | Pull Request                                             | Subject                                                                                                                                                                    |
+|:--------|:-----------|:---------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.3.0   | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures                                                                                                                   |
+| 0.2.2   | 2024-02-12 | [35150](https://github.com/airbytehq/airbyte/pull/35150) | Manage dependencies with Poetry.                                                                                                                                           |
+| 0.2.1   | 2024-01-12 | [1234](https://github.com/airbytehq/airbyte/pull/1234)   | prepare for airbyte-lib                                                                                                                                                    |
 | 0.2.0   | 2023-09-29 | [28457](https://github.com/airbytehq/airbyte/pull/30931) | Added `userId` to `email_bounce`, `email_click`, `email_complaint`, `email_open`, `email_send` `email_send_skip`, `email_subscribe`, `email_unsubscribe`, `events` streams |
-| 0.1.31 | 2023-12-06 | [33106](https://github.com/airbytehq/airbyte/pull/33106) | Base image migration: remove Dockerfile and use the python-connector-base image |
-| 0.1.30  | 2023-07-19 | [28457](https://github.com/airbytehq/airbyte/pull/28457) | Fixed TypeError for StreamSlice in debug mode                                                                |
-| 0.1.29  | 2023-05-24 | [26459](https://github.com/airbytehq/airbyte/pull/26459) | Added requests reading timeout 300 seconds                                                                   |
-| 0.1.28  | 2023-05-12 | [26014](https://github.com/airbytehq/airbyte/pull/26014) | Improve 500 handling for Events stream                                                                       |
-| 0.1.27  | 2023-04-06 | [24962](https://github.com/airbytehq/airbyte/pull/24962) | `UserList` stream when meet `500 - Generic Error` will skip a broken slice and keep going with the next one  |
-| 0.1.26  | 2023-03-10 | [23938](https://github.com/airbytehq/airbyte/pull/23938) | Improve retry for `500 - Generic Error`                                                                      |
-| 0.1.25  | 2023-03-07 | [23821](https://github.com/airbytehq/airbyte/pull/23821) | Added retry for `500 - Generic Error`, increased max attempts number to `6` to handle `ChunkedEncodingError` |
-| 0.1.24  | 2023-02-14 | [22979](https://github.com/airbytehq/airbyte/pull/22979) | Specified date formatting in specification                                                                   |
-| 0.1.23  | 2023-01-27 | [22011](https://github.com/airbytehq/airbyte/pull/22011) | Set `AvailabilityStrategy` for streams explicitly to `None`                                                  |
-| 0.1.22  | 2022-11-30 | [19913](https://github.com/airbytehq/airbyte/pull/19913) | Replace pendulum.parse -> dateutil.parser.parse to avoid memory leak                                         |
-| 0.1.21  | 2022-10-27 | [18537](https://github.com/airbytehq/airbyte/pull/18537) | Improve streams discovery                                                                                    |
-| 0.1.20  | 2022-10-21 | [18292](https://github.com/airbytehq/airbyte/pull/18292) | Better processing of 401 and 429 errors                                                                      |
-| 0.1.19  | 2022-10-05 | [17602](https://github.com/airbytehq/airbyte/pull/17602) | Add check for stream permissions                                                                             |
-| 0.1.18  | 2022-10-04 | [17573](https://github.com/airbytehq/airbyte/pull/17573) | Limit time range for SATs                                                                                    |
-| 0.1.17  | 2022-09-02 | [16067](https://github.com/airbytehq/airbyte/pull/16067) | added new events streams                                                                                     |
-| 0.1.16  | 2022-08-15 | [15670](https://github.com/airbytehq/airbyte/pull/15670) | Api key is passed via header                                                                                 |
-| 0.1.15  | 2021-12-06 | [8524](https://github.com/airbytehq/airbyte/pull/8524)   | Update connector fields title/description                                                                    |
-| 0.1.14  | 2021-12-01 | [8380](https://github.com/airbytehq/airbyte/pull/8380)   | Update `Events` stream to use `export/userEvents` endpoint                                                   |
-| 0.1.13  | 2021-11-22 | [8091](https://github.com/airbytehq/airbyte/pull/8091)   | Adjust slice ranges for email streams                                                                        |
-| 0.1.12  | 2021-11-09 | [7780](https://github.com/airbytehq/airbyte/pull/7780)   | Split EmailSend stream into slices to fix premature connection close error                                   |
-| 0.1.11  | 2021-11-03 | [7619](https://github.com/airbytehq/airbyte/pull/7619)   | Bugfix type error while incrementally loading the `Templates` stream                                         |
-| 0.1.10  | 2021-11-03 | [7591](https://github.com/airbytehq/airbyte/pull/7591)   | Optimize export streams memory consumption for large requests                                                |
-| 0.1.9   | 2021-10-06 | [5915](https://github.com/airbytehq/airbyte/pull/5915)   | Enable campaign_metrics stream                                                                               |
-| 0.1.8   | 2021-09-20 | [5915](https://github.com/airbytehq/airbyte/pull/5915)   | Add new streams: campaign_metrics, events                                                                    |
-| 0.1.7   | 2021-09-20 | [6242](https://github.com/airbytehq/airbyte/pull/6242)   | Updated schema for: campaigns, lists, templates, metadata                                                    |
+| 0.1.31  | 2023-12-06 | [33106](https://github.com/airbytehq/airbyte/pull/33106) | Base image migration: remove Dockerfile and use the python-connector-base image                                                                                            |
+| 0.1.30  | 2023-07-19 | [28457](https://github.com/airbytehq/airbyte/pull/28457) | Fixed TypeError for StreamSlice in debug mode                                                                                                                              |
+| 0.1.29  | 2023-05-24 | [26459](https://github.com/airbytehq/airbyte/pull/26459) | Added requests reading timeout 300 seconds                                                                                                                                 |
+| 0.1.28  | 2023-05-12 | [26014](https://github.com/airbytehq/airbyte/pull/26014) | Improve 500 handling for Events stream                                                                                                                                     |
+| 0.1.27  | 2023-04-06 | [24962](https://github.com/airbytehq/airbyte/pull/24962) | `UserList` stream when meet `500 - Generic Error` will skip a broken slice and keep going with the next one                                                                |
+| 0.1.26  | 2023-03-10 | [23938](https://github.com/airbytehq/airbyte/pull/23938) | Improve retry for `500 - Generic Error`                                                                                                                                    |
+| 0.1.25  | 2023-03-07 | [23821](https://github.com/airbytehq/airbyte/pull/23821) | Added retry for `500 - Generic Error`, increased max attempts number to `6` to handle `ChunkedEncodingError`                                                               |
+| 0.1.24  | 2023-02-14 | [22979](https://github.com/airbytehq/airbyte/pull/22979) | Specified date formatting in specification                                                                                                                                 |
+| 0.1.23  | 2023-01-27 | [22011](https://github.com/airbytehq/airbyte/pull/22011) | Set `AvailabilityStrategy` for streams explicitly to `None`                                                                                                                |
+| 0.1.22  | 2022-11-30 | [19913](https://github.com/airbytehq/airbyte/pull/19913) | Replace pendulum.parse -> dateutil.parser.parse to avoid memory leak                                                                                                       |
+| 0.1.21  | 2022-10-27 | [18537](https://github.com/airbytehq/airbyte/pull/18537) | Improve streams discovery                                                                                                                                                  |
+| 0.1.20  | 2022-10-21 | [18292](https://github.com/airbytehq/airbyte/pull/18292) | Better processing of 401 and 429 errors                                                                                                                                    |
+| 0.1.19  | 2022-10-05 | [17602](https://github.com/airbytehq/airbyte/pull/17602) | Add check for stream permissions                                                                                                                                           |
+| 0.1.18  | 2022-10-04 | [17573](https://github.com/airbytehq/airbyte/pull/17573) | Limit time range for SATs                                                                                                                                                  |
+| 0.1.17  | 2022-09-02 | [16067](https://github.com/airbytehq/airbyte/pull/16067) | added new events streams                                                                                                                                                   |
+| 0.1.16  | 2022-08-15 | [15670](https://github.com/airbytehq/airbyte/pull/15670) | Api key is passed via header                                                                                                                                               |
+| 0.1.15  | 2021-12-06 | [8524](https://github.com/airbytehq/airbyte/pull/8524)   | Update connector fields title/description                                                                                                                                  |
+| 0.1.14  | 2021-12-01 | [8380](https://github.com/airbytehq/airbyte/pull/8380)   | Update `Events` stream to use `export/userEvents` endpoint                                                                                                                 |
+| 0.1.13  | 2021-11-22 | [8091](https://github.com/airbytehq/airbyte/pull/8091)   | Adjust slice ranges for email streams                                                                                                                                      |
+| 0.1.12  | 2021-11-09 | [7780](https://github.com/airbytehq/airbyte/pull/7780)   | Split EmailSend stream into slices to fix premature connection close error                                                                                                 |
+| 0.1.11  | 2021-11-03 | [7619](https://github.com/airbytehq/airbyte/pull/7619)   | Bugfix type error while incrementally loading the `Templates` stream                                                                                                       |
+| 0.1.10  | 2021-11-03 | [7591](https://github.com/airbytehq/airbyte/pull/7591)   | Optimize export streams memory consumption for large requests                                                                                                              |
+| 0.1.9   | 2021-10-06 | [5915](https://github.com/airbytehq/airbyte/pull/5915)   | Enable campaign_metrics stream                                                                                                                                             |
+| 0.1.8   | 2021-09-20 | [5915](https://github.com/airbytehq/airbyte/pull/5915)   | Add new streams: campaign_metrics, events                                                                                                                                  |
+| 0.1.7   | 2021-09-20 | [6242](https://github.com/airbytehq/airbyte/pull/6242)   | Updated schema for: campaigns, lists, templates, metadata                                                                                                                  |
diff --git a/docs/integrations/sources/linkedin-ads.md b/docs/integrations/sources/linkedin-ads.md
index 16bb49f70e1d..858c297f7958 100644
--- a/docs/integrations/sources/linkedin-ads.md
+++ b/docs/integrations/sources/linkedin-ads.md
@@ -170,7 +170,8 @@ After 5 unsuccessful attempts - the connector will stop the sync operation. In s
 ## Changelog
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                         |
-| :------ | :--------- | :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
+|:--------|:-----------|:---------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------|
+| 0.7.0   | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures                                                        |
 | 0.6.8   | 2024-02-09 | [35086](https://github.com/airbytehq/airbyte/pull/35086) | Manage dependencies with Poetry.                                                                                |
 | 0.6.7   | 2024-01-11 | [34152](https://github.com/airbytehq/airbyte/pull/34152) | prepare for airbyte-lib                                                                                         |
 | 0.6.6   | 2024-01-15 | [34222](https://github.com/airbytehq/airbyte/pull/34222) | Use stream slices for Analytics streams                                                                         |
diff --git a/docs/integrations/sources/paypal-transaction.md b/docs/integrations/sources/paypal-transaction.md
index 1c9504f55344..50df0f002d98 100644
--- a/docs/integrations/sources/paypal-transaction.md
+++ b/docs/integrations/sources/paypal-transaction.md
@@ -279,12 +279,13 @@ ___
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                                      |
 |:--------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|
-| 2.3.0   | 2024-02-014 | [34510](https://github.com/airbytehq/airbyte/pull/34510) | Silver certified. New Streams Added                                                        |
-| 2.2.2   | 2024-02-09 | [35075](https://github.com/airbytehq/airbyte/pull/35075) | Manage dependencies with Poetry. 
-| 2.2.1   | 2024-01-11 | [34155](https://github.com/airbytehq/airbyte/pull/34155) | prepare for airbyte-lib                                                        |
-| 2.2.0 | 2023-10-25 | [31852](https://github.com/airbytehq/airbyte/pull/31852) | The size of the time_window can be configured                                                                               |
-| 2.1.2 | 2023-10-23 | [31759](https://github.com/airbytehq/airbyte/pull/31759) | Keep transaction_id as a string and fetch data in 7-day batches
-| 2.1.1 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image                                              |
+| 2.4.0   | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures                                                                     |
+| 2.3.0   | 2024-02-14 | [34510](https://github.com/airbytehq/airbyte/pull/34510) | Silver certified. New Streams Added                                                                                          |
+| 2.2.2   | 2024-02-09 | [35075](https://github.com/airbytehq/airbyte/pull/35075) | Manage dependencies with Poetry.                                                                                             |
+| 2.2.1   | 2024-01-11 | [34155](https://github.com/airbytehq/airbyte/pull/34155) | prepare for airbyte-lib                                                                                                      |
+| 2.2.0   | 2023-10-25 | [31852](https://github.com/airbytehq/airbyte/pull/31852) | The size of the time_window can be configured                                                                                |
+| 2.1.2   | 2023-10-23 | [31759](https://github.com/airbytehq/airbyte/pull/31759) | Keep transaction_id as a string and fetch data in 7-day batches                                                              |
+| 2.1.1   | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image                                              |
 | 2.1.0   | 2023-08-14 | [29223](https://github.com/airbytehq/airbyte/pull/29223) | Migrate Python CDK to Low Code schema                                                                                        |
 | 2.0.0   | 2023-07-05 | [27916](https://github.com/airbytehq/airbyte/pull/27916) | Update `Balances` schema                                                                                                     |
 | 1.0.0   | 2023-07-03 | [27968](https://github.com/airbytehq/airbyte/pull/27968) | mark `Client ID` and `Client Secret` as required fields                                                                      |
diff --git a/docs/integrations/sources/pinterest.md b/docs/integrations/sources/pinterest.md
index bf57fd7d79a3..3dbd7a7b8227 100644
--- a/docs/integrations/sources/pinterest.md
+++ b/docs/integrations/sources/pinterest.md
@@ -129,7 +129,8 @@ The connector is restricted by the Pinterest [requests limitation](https://devel
 
 | Version | Date       | Pull Request                                             | Subject                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
 |:--------|:-----------| :------------------------------------------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| 1.1.1 | 2024-02-12 | [35159](https://github.com/airbytehq/airbyte/pull/35159) | Manage dependencies with Poetry. |
+| 1.2.0   | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures                                                                                                                                                                                                                                                                                                                                                                                                |
+| 1.1.1   | 2024-02-12 | [35159](https://github.com/airbytehq/airbyte/pull/35159) | Manage dependencies with Poetry.                                                                                                                                                                                                                                                                                                                                                                                                                        |
 | 1.1.0   | 2023-11-22 | [32747](https://github.com/airbytehq/airbyte/pull/32747) | Update docs and spec. Add missing `placement_traffic_type` field to AdGroups stream                                                                                                                                                                                                                                                                                                                                                                     |
 | 1.0.0   | 2023-11-16 | [32595](https://github.com/airbytehq/airbyte/pull/32595) | Add airbyte_type: timestamp_without_timezone to date-time fields across all streams. Rename `Advertizer*` streams to `Advertiser*`                                                                                                                                                                                                                                                                                                                      |
 | 0.8.2   | 2023-11-20 | [32672](https://github.com/airbytehq/airbyte/pull/32672) | Fix backoff waiting time                                                                                                                                                                                                                                                                                                                                                                                                                                |

From 970b24b30c53275e4b8c6ab593546a5d7825b06e Mon Sep 17 00:00:00 2001
From: Artem Inzhyyants <36314070+artem1205@users.noreply.github.com>
Date: Thu, 22 Feb 2024 20:06:53 +0100
Subject: [PATCH 30/74] Airbyte CDK: add CustomRecordFilter (#35283)

Signed-off-by: Artem Inzhyyants 
---
 .../declarative_component_schema.yaml         | 25 ++++++++++++++++++-
 .../models/declarative_component_schema.py    | 16 +++++++++++-
 .../parsers/model_to_component_factory.py     |  2 ++
 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
index 7e85d080c601..69cf2f8d1bbb 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/declarative_component_schema.yaml
@@ -516,6 +516,27 @@ definitions:
       $parameters:
         type: object
         additionalProperties: true
+  CustomRecordFilter:
+    title: Custom Record Filter
+    description: Record filter component whose behavior is derived from a custom code implementation of the connector.
+    type: object
+    additionalProperties: true
+    required:
+      - type
+      - class_name
+    properties:
+      type:
+        type: string
+        enum: [CustomRecordFilter]
+      class_name:
+        title: Class Name
+        description: Fully-qualified name of the class that will be implementing the custom record filter strategy. The format is `source_..`.
+        type: string
+        examples:
+          - "source_railz.components.MyCustomCustomRecordFilter"
+      $parameters:
+        type: object
+        additionalProperties: true
   CustomRequester:
     title: Custom Requester
     description: Requester component whose behavior is derived from a custom code implementation of the connector.
@@ -1819,7 +1840,9 @@ definitions:
       record_filter:
         title: Record Filter
         description: Responsible for filtering records to be emitted by the Source.
-        "$ref": "#/definitions/RecordFilter"
+        anyOf:
+          - "$ref": "#/definitions/CustomRecordFilter"
+          - "$ref": "#/definitions/RecordFilter"
       schema_normalization:
         "$ref": "#/definitions/SchemaNormalization"
         default: None
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
index 182c0d5e3690..f70d3aef7523 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/models/declarative_component_schema.py
@@ -152,6 +152,20 @@ class Config:
     parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
 
 
+class CustomRecordFilter(BaseModel):
+    class Config:
+        extra = Extra.allow
+
+    type: Literal['CustomRecordFilter']
+    class_name: str = Field(
+        ...,
+        description='Fully-qualified name of the class that will be implementing the custom record filtering. The format is `source_..`.',
+        examples=['source_railz.components.MyCustomRecordFilter'],
+        title='Class Name',
+    )
+    parameters: Optional[Dict[str, Any]] = Field(None, alias='$parameters')
+
+
 class CustomRequester(BaseModel):
     class Config:
         extra = Extra.allow
@@ -1019,7 +1033,7 @@ class ListPartitionRouter(BaseModel):
 class RecordSelector(BaseModel):
     type: Literal["RecordSelector"]
     extractor: Union[CustomRecordExtractor, DpathExtractor]
-    record_filter: Optional[RecordFilter] = Field(
+    record_filter: Optional[Union[RecordFilter, CustomRecordFilter]] = Field(
         None,
         description="Responsible for filtering records to be emitted by the Source.",
         title="Record Filter",
diff --git a/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py b/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py
index 380435c06a4e..45a44a97b04b 100644
--- a/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py
+++ b/airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py
@@ -46,6 +46,7 @@
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomPaginationStrategy as CustomPaginationStrategyModel
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomPartitionRouter as CustomPartitionRouterModel
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomRecordExtractor as CustomRecordExtractorModel
+from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomRecordFilter as CustomRecordFilterModel
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomRequester as CustomRequesterModel
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomRetriever as CustomRetrieverModel
 from airbyte_cdk.sources.declarative.models.declarative_component_schema import CustomTransformation as CustomTransformationModel
@@ -161,6 +162,7 @@ def _init_mappings(self) -> None:
             CustomErrorHandlerModel: self.create_custom_component,
             CustomIncrementalSyncModel: self.create_custom_component,
             CustomRecordExtractorModel: self.create_custom_component,
+            CustomRecordFilterModel: self.create_custom_component,
             CustomRequesterModel: self.create_custom_component,
             CustomRetrieverModel: self.create_custom_component,
             CustomPaginationStrategyModel: self.create_custom_component,

From fbe0e8c6f36ac4067d66f11e1a0956f1827dc8d9 Mon Sep 17 00:00:00 2001
From: artem1205 
Date: Thu, 22 Feb 2024 19:12:42 +0000
Subject: [PATCH 31/74] =?UTF-8?q?=F0=9F=A4=96=20Bump=20minor=20version=20o?=
 =?UTF-8?q?f=20Python=20CDK?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 airbyte-cdk/python/.bumpversion.cfg | 2 +-
 airbyte-cdk/python/CHANGELOG.md     | 3 +++
 airbyte-cdk/python/Dockerfile       | 4 ++--
 airbyte-cdk/python/setup.py         | 2 +-
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/airbyte-cdk/python/.bumpversion.cfg b/airbyte-cdk/python/.bumpversion.cfg
index 286c6a02b098..cae50f52aa81 100644
--- a/airbyte-cdk/python/.bumpversion.cfg
+++ b/airbyte-cdk/python/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.66.0
+current_version = 0.67.0
 commit = False
 
 [bumpversion:file:setup.py]
diff --git a/airbyte-cdk/python/CHANGELOG.md b/airbyte-cdk/python/CHANGELOG.md
index bf0575a22c23..aafd9d33a8a7 100644
--- a/airbyte-cdk/python/CHANGELOG.md
+++ b/airbyte-cdk/python/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Changelog
 
+## 0.67.0
+Low-code: Add CustomRecordFilter
+
 ## 0.66.0
 Low-code: Add interpolation for request options
 
diff --git a/airbyte-cdk/python/Dockerfile b/airbyte-cdk/python/Dockerfile
index d98aefd1ff43..2c1ea428129c 100644
--- a/airbyte-cdk/python/Dockerfile
+++ b/airbyte-cdk/python/Dockerfile
@@ -10,7 +10,7 @@ RUN apk --no-cache upgrade \
     && apk --no-cache add tzdata build-base
 
 # install airbyte-cdk
-RUN pip install --prefix=/install airbyte-cdk==0.66.0
+RUN pip install --prefix=/install airbyte-cdk==0.67.0
 
 # build a clean environment
 FROM base
@@ -32,5 +32,5 @@ ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
 ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]
 
 # needs to be the same as CDK
-LABEL io.airbyte.version=0.66.0
+LABEL io.airbyte.version=0.67.0
 LABEL io.airbyte.name=airbyte/source-declarative-manifest
diff --git a/airbyte-cdk/python/setup.py b/airbyte-cdk/python/setup.py
index 83405018d9e2..b441974dc1bb 100644
--- a/airbyte-cdk/python/setup.py
+++ b/airbyte-cdk/python/setup.py
@@ -36,7 +36,7 @@
     name="airbyte-cdk",
     # The version of the airbyte-cdk package is used at runtime to validate manifests. That validation must be
     # updated if our semver format changes such as using release candidate versions.
-    version="0.66.0",
+    version="0.67.0",
     description="A framework for writing Airbyte Connectors.",
     long_description=README,
     long_description_content_type="text/markdown",

From 4e548d3c2d6c964f55c3ced722f3a557ad395c6d Mon Sep 17 00:00:00 2001
From: Evan Tahler 
Date: Thu, 22 Feb 2024 12:05:36 -0800
Subject: [PATCH 32/74] Do not add connector header to source and destination
 index pages (#35553)

---
 docusaurus/src/components/HeaderDecoration.jsx | 2 +-
 docusaurus/src/remark/utils.js                 | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/docusaurus/src/components/HeaderDecoration.jsx b/docusaurus/src/components/HeaderDecoration.jsx
index 01f43e5570cb..875396216ba3 100644
--- a/docusaurus/src/components/HeaderDecoration.jsx
+++ b/docusaurus/src/components/HeaderDecoration.jsx
@@ -85,7 +85,7 @@ export const HeaderDecoration = ({
         

{isArchived ? ( - {originalTitle} [ARCHIVED] + {originalTitle} [ARCHIVED] ) : ( originalTitle diff --git a/docusaurus/src/remark/utils.js b/docusaurus/src/remark/utils.js index e28710264693..bd5544ff0fe4 100644 --- a/docusaurus/src/remark/utils.js +++ b/docusaurus/src/remark/utils.js @@ -8,6 +8,11 @@ const isDocsPage = (vfile) => { return false; } + // skip the root files in integrations/source and integrations/destinations + if (vfile.path.includes("README.md")) { + return false; + } + if (vfile.path.includes("-migrations.md")) { return false; } From 8707fb9fd9e2e607b6cc1ac42611dd4c37071f78 Mon Sep 17 00:00:00 2001 From: Augustin Date: Thu, 22 Feb 2024 21:44:44 +0100 Subject: [PATCH 33/74] gradle.yml: fix path filters (#35554) --- .github/workflows/gradle.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9d9234b5a5ca..24e55f6d4016 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,25 +22,26 @@ on: jobs: changes: runs-on: ubuntu-latest + outputs: + java: ${{ steps.changes.outputs.java }} + python_cdk: ${{ steps.changes.outputs.python_cdk }} + steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Get changed files - uses: tj-actions/changed-files@v39 - id: changes + - id: changes + uses: dorny/paths-filter@v2 with: - files_yaml: | - gradlecheck: + # Note: expressions within a filter are OR'ed + filters: | + java: - '**/*.java' - '**/*.gradle' - 'airbyte-cdk/java/**/*' - outputs: - gradle: ${{ steps.changes.outputs.gradlecheck_any_changed }} - + python_cdk: + - 'airbyte-cdk/python/**/*' run-check: needs: - changes - if: needs.changes.outputs.gradle == 'true' + if: needs.changes.outputs.java == 'true' # The gradle check task which we will run is embarrassingly parallelizable. # We therefore run this on a machine with a maximum number of cores. # We pay per time and per core, so there should be little difference in total cost. From 98ed5018603cbfe1ecd7202eadc692faa697cafc Mon Sep 17 00:00:00 2001 From: "Roman Yermilov [GL]" <86300758+roman-yermilov-gl@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:54:41 +0100 Subject: [PATCH 34/74] Source Monday: fix gql query to support inline fragment value for the Items stream (#35506) --- .../integration_tests/expected_records.jsonl | 2 +- .../connectors/source-monday/metadata.yaml | 2 +- .../connectors/source-monday/pyproject.toml | 2 +- .../source_monday/graphql_requester.py | 22 +++++++++++++++++++ .../source_monday/schemas/items.json | 3 ++- docs/integrations/sources/monday.md | 3 ++- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/airbyte-integrations/connectors/source-monday/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-monday/integration_tests/expected_records.jsonl index 8c9370bc4be5..21febb1c0f36 100644 --- a/airbyte-integrations/connectors/source-monday/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-monday/integration_tests/expected_records.jsonl @@ -1,4 +1,4 @@ -{"stream": "items", "data": {"id": "4635211945", "name": "Item 1", "assets": [], "board": {"id": "4635211873"}, "column_values": [{"id": "person", "text": "", "type": "people", "value": null}, {"id": "status", "text": "Working on it", "type": "status", "value": "{\"index\":0,\"post_id\":null,\"changed_at\":\"2019-03-01T17:24:57.321Z\"}"}, {"id": "date4", "text": "2023-06-11", "type": "date", "value": "{\"date\":\"2023-06-11\",\"icon\":null,\"changed_at\":\"2023-06-13T13:58:25.871Z\"}"}, {"id": "tags", "text": "open", "type": "tags", "value": "{\"tag_ids\":[19038090]}"}], "created_at": "2023-06-13T13:58:24Z", "creator_id": "36694549", "group": {"id": "topics"}, "parent_item": null, "state": "active", "subscribers": [{"id": "36694549"}], "updated_at": "2023-06-15T16:19:37Z", "updates": [{"id": "2223820299"}, {"id": "2223818363"}], "updated_at_int": 1686845977}, "emitted_at": 1705072697006} +{"stream": "items", "data": {"id": "4635211945", "name": "Item 1", "assets": [], "board": {"id": "4635211873"}, "column_values": [{"id": "person", "text": "", "type": "people", "value": null}, {"id": "status", "text": "Working on it", "type": "status", "value": "{\"index\":0,\"post_id\":null,\"changed_at\":\"2019-03-01T17:24:57.321Z\"}"}, {"id": "date4", "text": "2023-06-11", "type": "date", "value": "{\"date\":\"2023-06-11\",\"icon\":null,\"changed_at\":\"2023-06-13T13:58:25.871Z\"}"}, {"id": "tags", "text": "open", "type": "tags", "value": "{\"tag_ids\":[19038090]}"}], "created_at": "2023-06-13T13:58:24Z", "creator_id": "36694549", "group": {"id": "topics"}, "parent_item": null, "state": "active", "subscribers": [{"id": "36694549"}], "updated_at": "2023-06-13T13:59:32Z", "updates": [{"id": "2223820299"}, {"id": "2223818363"}], "updated_at_int": 1686664772}, "emitted_at": 1708603933827} {"stream": "boards", "data": {"id": "3555407826", "name": "Procurement process", "board_kind": "public", "type": "board", "columns": [{"archived": false, "description": null, "id": "name", "settings_str": "{}", "title": "Name", "type": "name", "width": 380}, {"archived": false, "description": null, "id": "manager1", "settings_str": "{}", "title": "Owner", "type": "people", "width": 80}, {"archived": false, "description": null, "id": "date4", "settings_str": "{}", "title": "Request date", "type": "date", "width": null}, {"archived": false, "description": null, "id": "status1", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"Evaluating\",\"1\":\"Done\",\"2\":\"Denied\",\"3\":\"Waiting for legal\",\"6\":\"Approved for POC\",\"11\":\"On hold\",\"14\":\"Waiting for vendor\",\"15\":\"Negotiation\",\"108\":\"Approved for use\"},\"labels_positions_v2\":{\"0\":0,\"1\":1,\"2\":7,\"3\":8,\"5\":9,\"6\":3,\"11\":6,\"14\":5,\"15\":4,\"108\":2},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"},\"3\":{\"color\":\"#0086c0\",\"border\":\"#3DB0DF\",\"var_name\":\"blue-links\"},\"6\":{\"color\":\"#037f4c\",\"border\":\"#006B38\",\"var_name\":\"grass-green\"},\"11\":{\"color\":\"#BB3354\",\"border\":\"#A42D4A\",\"var_name\":\"dark-red\"},\"14\":{\"color\":\"#784BD1\",\"border\":\"#8F4DC4\",\"var_name\":\"dark-purple\"},\"15\":{\"color\":\"#9CD326\",\"border\":\"#89B921\",\"var_name\":\"lime-green\"},\"108\":{\"color\":\"#4eccc6\",\"border\":\"#4eccc6\",\"var_name\":\"australia\"}}}", "title": "Procurement status", "type": "status", "width": null}, {"archived": false, "description": null, "id": "person", "settings_str": "{}", "title": "Manager", "type": "people", "width": 80}, {"archived": false, "description": null, "id": "status", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Manager approval", "type": "status", "width": null}, {"archived": false, "description": null, "id": "budget_owner", "settings_str": "{}", "title": "POC owner", "type": "people", "width": 80}, {"archived": false, "description": null, "id": "budget_owner_approval4", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "POC status", "type": "status", "width": null}, {"archived": false, "description": null, "id": "manager", "settings_str": "{}", "title": "Budget owner", "type": "people", "width": 80}, {"archived": false, "description": null, "id": "status4", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Budget owner approval", "type": "status", "width": 185}, {"archived": false, "description": null, "id": "people", "settings_str": "{}", "title": "Procurement team", "type": "people", "width": null}, {"archived": false, "description": null, "id": "budget_owner_approval", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Procurement approval", "type": "status", "width": null}, {"archived": false, "description": null, "id": "procurement_team", "settings_str": "{}", "title": "Finance", "type": "people", "width": null}, {"archived": false, "description": null, "id": "procurement_approval", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Finance approval", "type": "status", "width": null}, {"archived": false, "description": null, "id": "finance", "settings_str": "{}", "title": "Legal", "type": "people", "width": null}, {"archived": false, "description": null, "id": "finance_approval", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Redlines\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Legal approval", "type": "status", "width": null}, {"archived": false, "description": null, "id": "file", "settings_str": "{}", "title": "File", "type": "file", "width": null}, {"archived": false, "description": null, "id": "legal", "settings_str": "{}", "title": "Security", "type": "people", "width": null}, {"archived": false, "description": null, "id": "legal_approval", "settings_str": "{\"done_colors\":[1],\"labels\":{\"0\":\"On Hold\",\"1\":\"Approved\",\"2\":\"Declined\"},\"labels_positions_v2\":{\"0\":0,\"1\":2,\"2\":1,\"5\":3},\"labels_colors\":{\"0\":{\"color\":\"#fdab3d\",\"border\":\"#E99729\",\"var_name\":\"orange\"},\"1\":{\"color\":\"#00c875\",\"border\":\"#00B461\",\"var_name\":\"green-shadow\"},\"2\":{\"color\":\"#e2445c\",\"border\":\"#CE3048\",\"var_name\":\"red-shadow\"}}}", "title": "Security approval", "type": "status", "width": null}, {"archived": false, "description": null, "id": "date", "settings_str": "{\"hide_footer\":false}", "title": "Renewal date", "type": "date", "width": null}, {"archived": false, "description": null, "id": "last_updated", "settings_str": "{}", "title": "Last updated", "type": "last_updated", "width": 129}], "communication": null, "description": "Many IT departments need to handle the procurement process for new services. The essence of this board is to streamline this process by providing an intuitive structure that supports collaboration and efficiency.", "groups": [{"archived": false, "color": "#579bfc", "deleted": false, "id": "topics", "position": "65536", "title": "Reviewing"}, {"archived": false, "color": "#FF642E", "deleted": false, "id": "new_group", "position": "98304.0", "title": "Corporate IT"}, {"archived": false, "color": "#037f4c", "deleted": false, "id": "new_group2816", "position": "114688.0", "title": "Finance"}], "owners": [{"id": "36694549"}], "creator": {"id": "36694549"}, "permissions": "everyone", "state": "active", "subscribers": [{"id": "36694549"}], "tags": [], "top_group": {"id": "topics"}, "updated_at": "2022-11-21T14:36:50Z", "updates": [], "views": [], "workspace": null, "updated_at_int": 1669041410}, "emitted_at": 1705073472066} {"stream": "tags", "data": {"color": "#00c875", "id": "19038090", "name": "open"}, "emitted_at": 1690884065804} {"stream": "tags", "data": {"color": "#fdab3d", "id": "19038091", "name": "closed"}, "emitted_at": 1690884065806} diff --git a/airbyte-integrations/connectors/source-monday/metadata.yaml b/airbyte-integrations/connectors/source-monday/metadata.yaml index 1eb7552a971a..919c28575e39 100644 --- a/airbyte-integrations/connectors/source-monday/metadata.yaml +++ b/airbyte-integrations/connectors/source-monday/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 80a54ea2-9959-4040-aac1-eee42423ec9b - dockerImageTag: 2.0.2 + dockerImageTag: 2.0.3 releases: breakingChanges: 2.0.0: diff --git a/airbyte-integrations/connectors/source-monday/pyproject.toml b/airbyte-integrations/connectors/source-monday/pyproject.toml index b65f91f64961..d40e70477332 100644 --- a/airbyte-integrations/connectors/source-monday/pyproject.toml +++ b/airbyte-integrations/connectors/source-monday/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.0.2" +version = "2.0.3" name = "source-monday" description = "Source implementation for Monday." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-monday/source_monday/graphql_requester.py b/airbyte-integrations/connectors/source-monday/source_monday/graphql_requester.py index fec0d06cbc3e..fb360b133ec9 100644 --- a/airbyte-integrations/connectors/source-monday/source_monday/graphql_requester.py +++ b/airbyte-integrations/connectors/source-monday/source_monday/graphql_requester.py @@ -79,6 +79,28 @@ def _build_query(self, object_name: str, field_schema: dict, **object_arguments) arguments = f"({arguments})" if arguments else "" fields = ",".join(fields) + # Essentially, we construct a query based on schema properties; however, some fields in the schema are conditional. + # These conditional fields can be obtained by defining them as inline fragments (The docs: https://spec.graphql.org/October2021/#sec-Inline-Fragments). + # This is an example of a query built for the Items stream, with a `display_value` property defined as an `MirrorValue` inline fragment: + # query { + # boards (limit:1) { + # items_page (limit:20) { + # , + # ..., + # column_values { + # id, + # text, + # type, + # value, + # ... on MirrorValue {display_value} + # } + # } + # } + # } + # When constructing a query, we replace the `display_value` field with the `... on MirrorValue {display_value}` inline fragment. + if object_name == "column_values" and "display_value" in fields: + fields = fields.replace("display_value", "... on MirrorValue{display_value}") + if object_name in ["items_page", "next_items_page"]: query = f"{object_name}{arguments}{{cursor,items{{{fields}}}}}" else: diff --git a/airbyte-integrations/connectors/source-monday/source_monday/schemas/items.json b/airbyte-integrations/connectors/source-monday/source_monday/schemas/items.json index a793a5b281b3..fb682608e71b 100644 --- a/airbyte-integrations/connectors/source-monday/source_monday/schemas/items.json +++ b/airbyte-integrations/connectors/source-monday/source_monday/schemas/items.json @@ -43,7 +43,8 @@ "id": { "type": ["null", "string"] }, "text": { "type": ["null", "string"] }, "type": { "type": ["null", "string"] }, - "value": { "type": ["null", "string"] } + "value": { "type": ["null", "string"] }, + "display_value": { "type": ["null", "string"] } } } }, diff --git a/docs/integrations/sources/monday.md b/docs/integrations/sources/monday.md index 92b973abe1e6..065bc3df1c89 100644 --- a/docs/integrations/sources/monday.md +++ b/docs/integrations/sources/monday.md @@ -74,7 +74,8 @@ The Monday connector should not run into Monday API limitations under normal usa | Version | Date | Pull Request | Subject | |:--------|:-----------|:----------------------------------------------------------|:------------------------------------------------------------------------| -| 2.0.2 | 2024-02-12 | [35146](https://github.com/airbytehq/airbyte/pull/35146) | Manage dependencies with Poetry. | +| 2.0.3 | 2024-02-21 | [35506](https://github.com/airbytehq/airbyte/pull/35506) | Support for column values of the mirror type for the `Items` stream. | +| 2.0.2 | 2024-02-12 | [35146](https://github.com/airbytehq/airbyte/pull/35146) | Manage dependencies with Poetry. | | 2.0.1 | 2024-02-08 | [35016](https://github.com/airbytehq/airbyte/pull/35016) | Migrated to the latest airbyte cdk | | 2.0.0 | 2024-01-12 | [34108](https://github.com/airbytehq/airbyte/pull/34108) | Migrated to the latest API version: 2024-01 | | 1.1.4 | 2023-12-13 | [33448](https://github.com/airbytehq/airbyte/pull/33448) | Increase test coverage and migrate to base image | From 77378169b24be6776c4b54b4ededd1d81d02ce8d Mon Sep 17 00:00:00 2001 From: Augustin Date: Thu, 22 Feb 2024 22:01:42 +0100 Subject: [PATCH 35/74] gradle.yml: checkout the repo when not PR trigger (#35558) --- .github/workflows/gradle.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 24e55f6d4016..2d85d117ccde 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,6 +27,9 @@ jobs: python_cdk: ${{ steps.changes.outputs.python_cdk }} steps: + - name: Checkout Airbyte + if: github.event_name != 'pull_request' + uses: actions/checkout@v3 - id: changes uses: dorny/paths-filter@v2 with: From 06d91e7ed31054d436e800b490378844facc4224 Mon Sep 17 00:00:00 2001 From: Augustin Date: Thu, 22 Feb 2024 22:43:11 +0100 Subject: [PATCH 36/74] airbyte-cdk [python]: re-enable tests in CI (#35560) Co-authored-by: Marius Posta --- .github/workflows/gradle.yml | 4 +- .github/workflows/python_cdk_tests.yml | 150 +++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/python_cdk_tests.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2d85d117ccde..45cfc134b28a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -24,7 +24,6 @@ jobs: runs-on: ubuntu-latest outputs: java: ${{ steps.changes.outputs.java }} - python_cdk: ${{ steps.changes.outputs.python_cdk }} steps: - name: Checkout Airbyte @@ -39,8 +38,7 @@ jobs: - '**/*.java' - '**/*.gradle' - 'airbyte-cdk/java/**/*' - python_cdk: - - 'airbyte-cdk/python/**/*' + run-check: needs: - changes diff --git a/.github/workflows/python_cdk_tests.yml b/.github/workflows/python_cdk_tests.yml new file mode 100644 index 000000000000..0873bf4d93ac --- /dev/null +++ b/.github/workflows/python_cdk_tests.yml @@ -0,0 +1,150 @@ +# THIS WORKFLOW SHOULD BE REPLACED BY A CLEANER ONE ONCE THE PYTHON CDK TESTS CAN BE RUN WITH POETRY +name: Python CDK Tests + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} + S3_BUILD_CACHE_SECRET_KEY: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} + +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + types: + - opened + - reopened + - synchronize + +jobs: + changes: + runs-on: ubuntu-latest + outputs: + python_cdk: ${{ steps.changes.outputs.python_cdk }} + steps: + - name: Checkout Airbyte + if: github.event_name != 'pull_request' + uses: actions/checkout@v3 + - id: changes + uses: dorny/paths-filter@v2 + with: + # Note: expressions within a filter are OR'ed + filters: | + python_cdk: + - 'airbyte-cdk/python/**/*' + run-python-cdk-check: + needs: + - changes + if: needs.changes.outputs.python_cdk == 'true' + runs-on: connector-test-large + name: Python CDK Tests + timeout-minutes: 30 + steps: + - name: Checkout Airbyte + uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: "zulu" + java-version: "21" + - name: Install Pip + run: curl -fsSL https://bootstrap.pypa.io/get-pip.py | python3 + - name: Install Pyenv + run: python3 -m pip install virtualenv --user + - name: cd airbyte-cdk/python + run: cd airbyte-cdk/python + - name: Run Gradle Check on Python CDK + uses: burrunan/gradle-cache-action@v1 + env: + CI: true + with: + job-id: python-cdk-check + read-only: ${{ github.ref != 'refs/heads/master' }} + gradle-distribution-sha-256-sum-warning: false + concurrent: true + arguments: --scan build + + set-instatus-incident-on-failure: + name: Create Instatus Incident on Failure + runs-on: ubuntu-latest + needs: + - run-python-cdk-check + if: ${{ failure() && github.ref == 'refs/heads/master' }} + steps: + - name: Call Instatus Webhook + uses: joelwmale/webhook-action@master + with: + url: ${{ secrets.INSTATUS_CONNECTOR_CI_WEBHOOK_URL }} + body: '{ "trigger": "down", "status": "HASISSUES" }' + + set-instatus-incident-on-success: + name: Create Instatus Incident on Success + runs-on: ubuntu-latest + needs: + - run-python-cdk-check + if: ${{ success() && github.ref == 'refs/heads/master' }} + steps: + - name: Call Instatus Webhook + uses: joelwmale/webhook-action@master + with: + url: ${{ secrets.INSTATUS_CONNECTOR_CI_WEBHOOK_URL }} + body: '{ "trigger": "up" }' + + notify-failure-slack-channel: + name: "Notify Slack Channel on Build Failures" + runs-on: ubuntu-latest + needs: + - run-python-cdk-check + if: ${{ failure() && github.ref == 'refs/heads/master' }} + steps: + - name: Checkout Airbyte + uses: actions/checkout@v3 + - name: Match GitHub User to Slack User + id: match-github-to-slack-user + uses: ./.github/actions/match-github-to-slack-user + env: + AIRBYTE_TEAM_BOT_SLACK_TOKEN: ${{ secrets.SLACK_AIRBYTE_TEAM_READ_USERS }} + GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Publish to OSS Build Failure Slack Channel + uses: abinoda/slack-action@master + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_AIRBYTE_TEAM }} + with: + args: >- + {\"channel\":\"C03BEADRPNY\", \"blocks\":[ + {\"type\":\"divider\"}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\" Merge to OSS Master failed! :bangbang: \n\n\"}}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"_merged by_: *${{ github.actor }}* \n\"}}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"<@${{ steps.match-github-to-slack-user.outputs.slack_user_ids }}> \n\"}}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\" :octavia-shocked: :octavia-shocked: \n\"}}, + {\"type\":\"divider\"}]} + + notify-failure-slack-channel-fixed-broken-build: + name: "Notify Slack Channel on Build Fixes" + runs-on: ubuntu-latest + needs: + - run-python-cdk-check + if: success() + steps: + - name: Get Previous Workflow Status + uses: Mercymeilya/last-workflow-status@v0.3 + id: last_status + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + # To avoid clogging up the channel, only publish build success if the previous build was a failure since this means the build was fixed. + - name: Publish Build Fixed Message to OSS Build Failure Slack Channel + if: ${{ steps.last_status.outputs.last_status == 'failure' }} + uses: abinoda/slack-action@master + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_AIRBYTE_TEAM }} + with: + args: >- + {\"channel\":\"C03BEADRPNY\", \"blocks\":[ + {\"type\":\"divider\"}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\" OSS Master Fixed! :white_check_mark: \n\n\"}}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"_merged by_: *${{ github.actor }}* \n\"}}, + {\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\" :octavia-rocket: :octavia-rocket: \n\"}}, + {\"type\":\"divider\"}]} From 3285fd279113049dc23328c14c14b6c04b34a82e Mon Sep 17 00:00:00 2001 From: David Wallace Date: Thu, 22 Feb 2024 13:57:41 -0800 Subject: [PATCH 37/74] =?UTF-8?q?=E2=9C=A8=20[source-mssql]=20skip=20sql?= =?UTF-8?q?=20server=20agent=20check=20if=20EngineEdition=20=3D=3D=208=20(?= =?UTF-8?q?#35368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source/mssql/MssqlSource.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java b/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java index 27bd0876a5dc..f7de282d5e8c 100644 --- a/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java +++ b/airbyte-integrations/connectors/source-mssql/src/main/java/io/airbyte/integrations/source/mssql/MssqlSource.java @@ -417,18 +417,27 @@ protected void assertCdcSchemaQueryable(final JsonNode config, final JdbcDatabas // todo: ensure this works for Azure managed SQL (since it uses different sql server agent) protected void assertSqlServerAgentRunning(final JdbcDatabase database) throws SQLException { try { - final List queryResponse = database.queryJsons(connection -> { - final String sql = - "SELECT status_desc FROM sys.dm_server_services WHERE [servicename] LIKE 'SQL Server Agent%' OR [servicename] LIKE 'SQL Server 代理%' "; - final PreparedStatement ps = connection.prepareStatement(sql); - LOGGER.info(String.format("Checking that the SQL Server Agent is running using the query: '%s'", sql)); - return ps; - }, sourceOperations::rowToJson); - - if (!(queryResponse.get(0).get("status_desc").toString().contains("Running"))) { - throw new RuntimeException(String.format( - "The SQL Server Agent is not running. Current state: '%s'. Please check the documentation on ensuring SQL Server Agent is running.", - queryResponse.get(0).get("status_desc").toString())); + // EngineEdition property values can be found at + // https://learn.microsoft.com/en-us/sql/t-sql/functions/serverproperty-transact-sql?view=sql-server-ver16 + // SQL Server Agent is always running on SQL Managed Instance: + // https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql#sql-server-agent + final Integer engineEdition = database.queryInt("SELECT ServerProperty('EngineEdition')"); + if (engineEdition == 8) { + LOGGER.info(String.format("SQL Server Agent is assumed to be running when EngineEdition == '%s'", engineEdition)); + } else { + final List queryResponse = database.queryJsons(connection -> { + final String sql = + "SELECT status_desc FROM sys.dm_server_services WHERE [servicename] LIKE 'SQL Server Agent%' OR [servicename] LIKE 'SQL Server 代理%' "; + final PreparedStatement ps = connection.prepareStatement(sql); + LOGGER.info(String.format("Checking that the SQL Server Agent is running using the query: '%s'", sql)); + return ps; + }, sourceOperations::rowToJson); + + if (!(queryResponse.get(0).get("status_desc").toString().contains("Running"))) { + throw new RuntimeException(String.format( + "The SQL Server Agent is not running. Current state: '%s'. Please check the documentation on ensuring SQL Server Agent is running.", + queryResponse.get(0).get("status_desc").toString())); + } } } catch (final Exception e) { if (e.getCause() != null && e.getCause().getClass().equals(com.microsoft.sqlserver.jdbc.SQLServerException.class)) { From 184d10967c6bad5fcbd825fedb089368e0f0fe6f Mon Sep 17 00:00:00 2001 From: Stephane Geneix <147216312+stephane-airbyte@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:37:27 -0800 Subject: [PATCH 38/74] push new source-mssql version (#35564) --- airbyte-integrations/connectors/source-mssql/metadata.yaml | 2 +- docs/integrations/sources/mssql.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-mssql/metadata.yaml b/airbyte-integrations/connectors/source-mssql/metadata.yaml index 3538ca06207a..1d13ccd7e9da 100644 --- a/airbyte-integrations/connectors/source-mssql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mssql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: b5ea17b1-f170-46dc-bc31-cc744ca984c1 - dockerImageTag: 3.7.1 + dockerImageTag: 3.7.2 dockerRepository: airbyte/source-mssql documentationUrl: https://docs.airbyte.com/integrations/sources/mssql githubIssueLabel: source-mssql diff --git a/docs/integrations/sources/mssql.md b/docs/integrations/sources/mssql.md index 3b1f397ced49..60dec7024ee9 100644 --- a/docs/integrations/sources/mssql.md +++ b/docs/integrations/sources/mssql.md @@ -342,6 +342,7 @@ WHERE actor_definition_id ='b5ea17b1-f170-46dc-bc31-cc744ca984c1' AND (configura | Version | Date | Pull Request | Subject | |:--------|:-----------|:------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.7.2 | 2024-02-21 | [35368](https://github.com/airbytehq/airbyte/pull/35368) | Change query syntax to make it compatible with Azure Synapse. | | 3.7.1 | 2024-02-20 | [35405](https://github.com/airbytehq/airbyte/pull/35405) | Change query syntax to make it compatible with Azure Synapse. | | 3.7.0 | 2024-01-30 | [33311](https://github.com/airbytehq/airbyte/pull/33311) | Source mssql with checkpointing initial sync. | | 3.6.1 | 2024-01-26 | [34573](https://github.com/airbytehq/airbyte/pull/34573) | Adopt CDK v0.16.0. | From ad227e5629f173b88a96aee3903810019c22b869 Mon Sep 17 00:00:00 2001 From: Gireesh Sreepathi Date: Thu, 22 Feb 2024 15:00:36 -0800 Subject: [PATCH 39/74] Destinations CDK: Refactor T+D to gather required world state upfront (#35342) Signed-off-by: Gireesh Sreepathi --- airbyte-cdk/java/airbyte-cdk/README.md | 191 +++++++++--------- .../util/ConnectorExceptionUtil.java | 12 ++ .../src/main/resources/version.properties | 2 +- .../jdbc/AbstractJdbcDestination.java | 10 +- .../destination/jdbc/ColumnDefinition.java | 11 +- .../destination/jdbc/CustomSqlType.java | 33 --- .../destination/jdbc/TableDefinition.java | 2 +- .../jdbc/TableSchemaRecordSet.java | 9 - .../destination/jdbc/TypeInfoRecordSet.java | 71 ------- .../JdbcDestinationHandler.java | 131 +++++++++--- .../typing_deduping/JdbcSqlGenerator.java | 3 +- .../typing_deduping/RawOnlySqlGenerator.kt | 7 - .../jdbc/AbstractJdbcDestinationTest.java | 7 + .../JdbcSqlGeneratorIntegrationTest.java | 3 +- .../concurrency/CompletableFutures.java | 52 ++++- .../io/airbyte/commons/functional/Either.java | 70 +++++++ .../concurrency/CompletableFuturesTest.java | 64 ++++++ .../BaseDestinationV1V2Migrator.java | 10 +- .../typing_deduping/CatalogParser.java | 6 +- .../typing_deduping/DefaultTyperDeduper.java | 85 ++++---- .../typing_deduping/DestinationHandler.java | 31 +-- .../DestinationInitialState.java | 23 +++ .../DestinationInitialStateImpl.java | 14 ++ .../DestinationV1V2Migrator.java | 6 +- .../typing_deduping/InitialRawTableState.java | 12 ++ .../NoOpDestinationV1V2Migrator.java | 6 +- .../NoOpTyperDeduperWithV1V2Migrations.java | 14 +- .../typing_deduping/SqlGenerator.java | 19 +- .../TypeAndDedupeTransaction.java | 14 +- .../typing_deduping/TyperDeduperUtil.kt | 2 +- .../typing_deduping/CatalogParserTest.java | 2 +- .../DefaultTyperDeduperTest.java | 116 ++++++----- .../DestinationV1V2MigratorTest.java | 2 +- .../typing_deduping/MockSqlGenerator.java | 7 +- .../BaseSqlGeneratorIntegrationTest.java | 114 +++++------ .../BaseTypingDedupingTest.java | 4 +- 36 files changed, 682 insertions(+), 483 deletions(-) delete mode 100644 airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/CustomSqlType.java delete mode 100644 airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableSchemaRecordSet.java delete mode 100644 airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TypeInfoRecordSet.java create mode 100644 airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/functional/Either.java create mode 100644 airbyte-cdk/java/airbyte-cdk/dependencies/src/test/java/io/airbyte/commons/concurrency/CompletableFuturesTest.java create mode 100644 airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialState.java create mode 100644 airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialStateImpl.java create mode 100644 airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/InitialRawTableState.java diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index 879286dc0785..f7a2891b540e 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -164,98 +164,99 @@ MavenLocal debugging steps: ### Java CDK -| Version | Date | Pull Request | Subject | -|:--------|:-----------|:-----------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Reduce CDC state compression limit to 1MB | -| 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | -| 0.21.2 | 2024-02-20 | [\#34978](https://github.com/airbytehq/airbyte/pull/34978) | Reduce log noise in NormalizationLogParser. | -| 0.21.1 | 2024-02-20 | [\#35199](https://github.com/airbytehq/airbyte/pull/35199) | Add thread names to the logs. | -| 0.21.0 | 2024-02-16 | [\#35314](https://github.com/airbytehq/airbyte/pull/35314) | Delete S3StreamCopier classes. These have been superseded by the async destinations framework. | -| 0.20.9 | 2024-02-15 | [\#35240](https://github.com/airbytehq/airbyte/pull/35240) | Make state emission to platform inside state manager itself. | -| 0.20.8 | 2024-02-15 | [\#35285](https://github.com/airbytehq/airbyte/pull/35285) | Improve blobstore module structure. | -| 0.20.7 | 2024-02-13 | [\#35236](https://github.com/airbytehq/airbyte/pull/35236) | output logs to files in addition to stdout when running tests | -| 0.20.6 | 2024-02-12 | [\#35036](https://github.com/airbytehq/airbyte/pull/35036) | Add trace utility to emit analytics messages. | -| 0.20.5 | 2024-02-13 | [\#34869](https://github.com/airbytehq/airbyte/pull/34869) | Don't emit final state in SourceStateIterator there is an underlying stream failure. | -| 0.20.4 | 2024-02-12 | [\#35042](https://github.com/airbytehq/airbyte/pull/35042) | Use delegate's isDestinationV2 invocation in SshWrappedDestination. | -| 0.20.3 | 2024-02-09 | [\#34580](https://github.com/airbytehq/airbyte/pull/34580) | Support special chars in mysql/mssql database name. | -| 0.20.2 | 2024-02-12 | [\#35111](https://github.com/airbytehq/airbyte/pull/35144) | Make state emission from async framework synchronized. | -| 0.20.1 | 2024-02-11 | [\#35111](https://github.com/airbytehq/airbyte/pull/35111) | Fix GlobalAsyncStateManager stats counting logic. | -| 0.20.0 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Add new test cases to BaseTypingDedupingTest to exercise special characters. | -| 0.19.0 | 2024-02-01 | [\#34745](https://github.com/airbytehq/airbyte/pull/34745) | Reorganize CDK module structure. | -| 0.18.0 | 2024-02-08 | [\#33606](https://github.com/airbytehq/airbyte/pull/33606) | Add updated Initial and Incremental Stream State definitions for DB Sources. | -| 0.17.1 | 2024-02-08 | [\#35027](https://github.com/airbytehq/airbyte/pull/35027) | Make state handling thread safe in async destination framework. | -| 0.17.0 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Enable configuring async destination batch size. | -| 0.16.6 | 2024-02-07 | [\#34892](https://github.com/airbytehq/airbyte/pull/34892) | Improved testcontainers logging and support for unshared containers. | -| 0.16.5 | 2024-02-07 | [\#34948](https://github.com/airbytehq/airbyte/pull/34948) | Fix source state stats counting logic | -| 0.16.4 | 2024-02-01 | [\#34727](https://github.com/airbytehq/airbyte/pull/34727) | Add future based stdout consumer in BaseTypingDedupingTest | -| 0.16.3 | 2024-01-30 | [\#34669](https://github.com/airbytehq/airbyte/pull/34669) | Fix org.apache.logging.log4j:log4j-slf4j-impl version conflicts. | -| 0.16.2 | 2024-01-29 | [\#34630](https://github.com/airbytehq/airbyte/pull/34630) | expose NamingTransformer to sub-classes in destinations JdbcSqlGenerator. | -| 0.16.1 | 2024-01-29 | [\#34533](https://github.com/airbytehq/airbyte/pull/34533) | Add a safe method to execute DatabaseMetadata's Resultset returning queries. | -| 0.16.0 | 2024-01-26 | [\#34573](https://github.com/airbytehq/airbyte/pull/34573) | Untangle Debezium harness dependencies. | -| 0.15.2 | 2024-01-25 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Improve airbyte-api build performance. | -| 0.15.1 | 2024-01-25 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Async destinations: Better logging when we fail to parse an AirbyteMessage | -| 0.15.0 | 2024-01-23 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Removed connector registry and micronaut dependencies. | -| 0.14.2 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Handle case-sensitivity in sentry error grouping | -| 0.14.1 | 2024-01-24 | [\#34468](https://github.com/airbytehq/airbyte/pull/34468) | Add wait for process to be done before ending sync in destination BaseTDTest | -| 0.14.0 | 2024-01-23 | [\#34461](https://github.com/airbytehq/airbyte/pull/34461) | Revert non backward compatible signature changes from 0.13.1 | -| 0.13.3 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Denote if destinations fully support Destinations V2 | -| 0.13.2 | 2024-01-18 | [\#34364](https://github.com/airbytehq/airbyte/pull/34364) | Better logging in mongo db source connector | -| 0.13.1 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Add postCreateTable hook in destination JdbcSqlGenerator | -| 0.13.0 | 2024-01-16 | [\#34177](https://github.com/airbytehq/airbyte/pull/34177) | Add `useExpensiveSafeCasting` param in JdbcSqlGenerator methods; add JdbcTypingDedupingTest fixture; other DV2-related changes | -| 0.12.1 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Add hook for additional destination specific checks to JDBC destination check method | -| 0.12.0 | 2024-01-10 | [\#33875](https://github.com/airbytehq/airbyte/pull/33875) | Upgrade sshd-mina to 2.11.1 | -| 0.11.5 | 2024-01-10 | [\#34119](https://github.com/airbytehq/airbyte/pull/34119) | Remove wal2json support for postgres+debezium. | -| 0.11.4 | 2024-01-09 | [\#33305](https://github.com/airbytehq/airbyte/pull/33305) | Source stats in incremental syncs | -| 0.11.3 | 2023-01-09 | [\#33658](https://github.com/airbytehq/airbyte/pull/33658) | Always fail when debezium fails, even if it happened during the setup phase. | -| 0.11.2 | 2024-01-09 | [\#33969](https://github.com/airbytehq/airbyte/pull/33969) | Destination state stats implementation | -| 0.11.1 | 2024-01-04 | [\#33727](https://github.com/airbytehq/airbyte/pull/33727) | SSH bastion heartbeats for Destinations | -| 0.11.0 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | DV2 T+D uses Sql struct to represent transactions; other T+D-related changes | -| 0.10.4 | 2023-12-20 | [\#33071](https://github.com/airbytehq/airbyte/pull/33071) | Add the ability to parse JDBC parameters with another delimiter than '&' | -| 0.10.3 | 2024-01-03 | [\#33312](https://github.com/airbytehq/airbyte/pull/33312) | Send out count in AirbyteStateMessage | -| 0.10.1 | 2023-12-21 | [\#33723](https://github.com/airbytehq/airbyte/pull/33723) | Make memory-manager log message less scary | -| 0.10.0 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | JdbcDestinationHandler now properly implements `getInitialRawTableState`; reenable SqlGenerator test | -| 0.9.0 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation, exclude the T&D module from the CDK | -| 0.8.0 | 2023-12-18 | [\#33506](https://github.com/airbytehq/airbyte/pull/33506) | Improve async destination shutdown logic; more JDBC async migration work; improve DAT test schema handling | -| 0.7.9 | 2023-12-18 | [\#33549](https://github.com/airbytehq/airbyte/pull/33549) | Improve MongoDB logging. | -| 0.7.8 | 2023-12-18 | [\#33365](https://github.com/airbytehq/airbyte/pull/33365) | Emit stream statuses more consistently | -| 0.7.7 | 2023-12-18 | [\#33434](https://github.com/airbytehq/airbyte/pull/33307) | Remove LEGACY state | -| 0.7.6 | 2023-12-14 | [\#32328](https://github.com/airbytehq/airbyte/pull/33307) | Add schema less mode for mongodb CDC. Fixes for non standard mongodb id type. | -| 0.7.4 | 2023-12-13 | [\#33232](https://github.com/airbytehq/airbyte/pull/33232) | Track stream record count during sync; only run T+D if a stream had nonzero records or the previous sync left unprocessed records. | -| 0.7.3 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Extract shared JDBC T+D code. | -| 0.7.2 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | Fix DV2 JDBC type mappings (code changes in [\#33307](https://github.com/airbytehq/airbyte/pull/33307)). | -| 0.7.1 | 2023-12-01 | [\#33027](https://github.com/airbytehq/airbyte/pull/33027) | Add the abstract DB source debugger. | -| 0.7.0 | 2023-12-07 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Destinations V2 changes for JDBC destinations | -| 0.6.4 | 2023-12-06 | [\#33082](https://github.com/airbytehq/airbyte/pull/33082) | Improvements to schema snapshot error handling + schema snapshot history scope (scoped to configured DB). | -| 0.6.2 | 2023-11-30 | [\#32573](https://github.com/airbytehq/airbyte/pull/32573) | Update MSSQLConverter to enforce 6-digit microsecond precision for timestamp fields | -| 0.6.1 | 2023-11-30 | [\#32610](https://github.com/airbytehq/airbyte/pull/32610) | Support DB initial sync using binary as primary key. | -| 0.6.0 | 2023-11-30 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | JDBC destinations now use the async framework | -| 0.5.3 | 2023-11-28 | [\#32686](https://github.com/airbytehq/airbyte/pull/32686) | Better attribution of debezium engine shutdown due to heartbeat. | -| 0.5.1 | 2023-11-27 | [\#32662](https://github.com/airbytehq/airbyte/pull/32662) | Debezium initialization wait time will now read from initial setup time. | -| 0.5.0 | 2023-11-22 | [\#32656](https://github.com/airbytehq/airbyte/pull/32656) | Introduce TestDatabase test fixture, refactor database source test base classes. | -| 0.4.11 | 2023-11-14 | [\#32526](https://github.com/airbytehq/airbyte/pull/32526) | Clean up memory manager logs. | -| 0.4.10 | 2023-11-13 | [\#32285](https://github.com/airbytehq/airbyte/pull/32285) | Fix UUID codec ordering for MongoDB connector | -| 0.4.9 | 2023-11-13 | [\#32468](https://github.com/airbytehq/airbyte/pull/32468) | Further error grouping improvements for DV2 connectors | -| 0.4.8 | 2023-11-09 | [\#32377](https://github.com/airbytehq/airbyte/pull/32377) | source-postgres tests: skip dropping database | -| 0.4.7 | 2023-11-08 | [\#31856](https://github.com/airbytehq/airbyte/pull/31856) | source-postgres: support for infinity date and timestamps | -| 0.4.5 | 2023-11-07 | [\#32112](https://github.com/airbytehq/airbyte/pull/32112) | Async destinations framework: Allow configuring the queue flush threshold | -| 0.4.4 | 2023-11-06 | [\#32119](https://github.com/airbytehq/airbyte/pull/32119) | Add STANDARD UUID codec to MongoDB debezium handler | -| 0.4.2 | 2023-11-06 | [\#32190](https://github.com/airbytehq/airbyte/pull/32190) | Improve error deinterpolation | -| 0.4.1 | 2023-11-02 | [\#32192](https://github.com/airbytehq/airbyte/pull/32192) | Add 's3-destinations' CDK module. | -| 0.4.0 | 2023-11-02 | [\#32050](https://github.com/airbytehq/airbyte/pull/32050) | Fix compiler warnings. | -| 0.3.0 | 2023-11-02 | [\#31983](https://github.com/airbytehq/airbyte/pull/31983) | Add deinterpolation feature to AirbyteExceptionHandler. | -| 0.2.4 | 2023-10-31 | [\#31807](https://github.com/airbytehq/airbyte/pull/31807) | Handle case of debezium update and delete of records in mongodb. | -| 0.2.3 | 2023-10-31 | [\#32022](https://github.com/airbytehq/airbyte/pull/32022) | Update Debezium version from 2.20 -> 2.4.0. | -| 0.2.2 | 2023-10-31 | [\#31976](https://github.com/airbytehq/airbyte/pull/31976) | Debezium tweaks to make tests run faster. | -| 0.2.0 | 2023-10-30 | [\#31960](https://github.com/airbytehq/airbyte/pull/31960) | Hoist top-level gradle subprojects into CDK. | -| 0.1.12 | 2023-10-24 | [\#31674](https://github.com/airbytehq/airbyte/pull/31674) | Fail sync when Debezium does not shut down properly. | -| 0.1.11 | 2023-10-18 | [\#31486](https://github.com/airbytehq/airbyte/pull/31486) | Update constants in AdaptiveSourceRunner. | -| 0.1.9 | 2023-10-12 | [\#31309](https://github.com/airbytehq/airbyte/pull/31309) | Use toPlainString() when handling BigDecimals in PostgresConverter | -| 0.1.8 | 2023-10-11 | [\#31322](https://github.com/airbytehq/airbyte/pull/31322) | Cap log line length to 32KB to prevent loss of records | -| 0.1.7 | 2023-10-10 | [\#31194](https://github.com/airbytehq/airbyte/pull/31194) | Deallocate unused per stream buffer memory when empty | -| 0.1.6 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | -| 0.1.5 | 2023-10-09 | [\#31196](https://github.com/airbytehq/airbyte/pull/31196) | Update typo in CDK (CDN_LSN -> CDC_LSN) | -| 0.1.4 | 2023-10-06 | [\#31139](https://github.com/airbytehq/airbyte/pull/31139) | Reduce async buffer | -| 0.1.1 | 2023-09-28 | [\#30835](https://github.com/airbytehq/airbyte/pull/30835) | JDBC destinations now avoid staging area name collisions by using the raw table name as the stage name. (previously we used the stream name as the stage name) | -| 0.1.0 | 2023-09-27 | [\#30445](https://github.com/airbytehq/airbyte/pull/30445) | First launch, including shared classes for all connectors. | -| 0.0.2 | 2023-08-21 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Version bump only (no other changes). | -| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | \ No newline at end of file +| Version | Date | Pull Request | Subject | +|:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.23.0 | 2024-02-22 | [\#35342](https://github.com/airbytehq/airbyte/pull/35342) | Consolidate and perform upfront gathering of DB metadata state | +| 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Reduce CDC state compression limit to 1MB | +| 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | +| 0.21.2 | 2024-02-20 | [\#34978](https://github.com/airbytehq/airbyte/pull/34978) | Reduce log noise in NormalizationLogParser. | +| 0.21.1 | 2024-02-20 | [\#35199](https://github.com/airbytehq/airbyte/pull/35199) | Add thread names to the logs. | +| 0.21.0 | 2024-02-16 | [\#35314](https://github.com/airbytehq/airbyte/pull/35314) | Delete S3StreamCopier classes. These have been superseded by the async destinations framework. | +| 0.20.9 | 2024-02-15 | [\#35240](https://github.com/airbytehq/airbyte/pull/35240) | Make state emission to platform inside state manager itself. | +| 0.20.8 | 2024-02-15 | [\#35285](https://github.com/airbytehq/airbyte/pull/35285) | Improve blobstore module structure. | +| 0.20.7 | 2024-02-13 | [\#35236](https://github.com/airbytehq/airbyte/pull/35236) | output logs to files in addition to stdout when running tests | +| 0.20.6 | 2024-02-12 | [\#35036](https://github.com/airbytehq/airbyte/pull/35036) | Add trace utility to emit analytics messages. | +| 0.20.5 | 2024-02-13 | [\#34869](https://github.com/airbytehq/airbyte/pull/34869) | Don't emit final state in SourceStateIterator there is an underlying stream failure. | +| 0.20.4 | 2024-02-12 | [\#35042](https://github.com/airbytehq/airbyte/pull/35042) | Use delegate's isDestinationV2 invocation in SshWrappedDestination. | +| 0.20.3 | 2024-02-09 | [\#34580](https://github.com/airbytehq/airbyte/pull/34580) | Support special chars in mysql/mssql database name. | +| 0.20.2 | 2024-02-12 | [\#35111](https://github.com/airbytehq/airbyte/pull/35144) | Make state emission from async framework synchronized. | +| 0.20.1 | 2024-02-11 | [\#35111](https://github.com/airbytehq/airbyte/pull/35111) | Fix GlobalAsyncStateManager stats counting logic. | +| 0.20.0 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Add new test cases to BaseTypingDedupingTest to exercise special characters. | +| 0.19.0 | 2024-02-01 | [\#34745](https://github.com/airbytehq/airbyte/pull/34745) | Reorganize CDK module structure. | +| 0.18.0 | 2024-02-08 | [\#33606](https://github.com/airbytehq/airbyte/pull/33606) | Add updated Initial and Incremental Stream State definitions for DB Sources. | +| 0.17.1 | 2024-02-08 | [\#35027](https://github.com/airbytehq/airbyte/pull/35027) | Make state handling thread safe in async destination framework. | +| 0.17.0 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Enable configuring async destination batch size. | +| 0.16.6 | 2024-02-07 | [\#34892](https://github.com/airbytehq/airbyte/pull/34892) | Improved testcontainers logging and support for unshared containers. | +| 0.16.5 | 2024-02-07 | [\#34948](https://github.com/airbytehq/airbyte/pull/34948) | Fix source state stats counting logic | +| 0.16.4 | 2024-02-01 | [\#34727](https://github.com/airbytehq/airbyte/pull/34727) | Add future based stdout consumer in BaseTypingDedupingTest | +| 0.16.3 | 2024-01-30 | [\#34669](https://github.com/airbytehq/airbyte/pull/34669) | Fix org.apache.logging.log4j:log4j-slf4j-impl version conflicts. | +| 0.16.2 | 2024-01-29 | [\#34630](https://github.com/airbytehq/airbyte/pull/34630) | expose NamingTransformer to sub-classes in destinations JdbcSqlGenerator. | +| 0.16.1 | 2024-01-29 | [\#34533](https://github.com/airbytehq/airbyte/pull/34533) | Add a safe method to execute DatabaseMetadata's Resultset returning queries. | +| 0.16.0 | 2024-01-26 | [\#34573](https://github.com/airbytehq/airbyte/pull/34573) | Untangle Debezium harness dependencies. | +| 0.15.2 | 2024-01-25 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Improve airbyte-api build performance. | +| 0.15.1 | 2024-01-25 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Async destinations: Better logging when we fail to parse an AirbyteMessage | +| 0.15.0 | 2024-01-23 | [\#34441](https://github.com/airbytehq/airbyte/pull/34441) | Removed connector registry and micronaut dependencies. | +| 0.14.2 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Handle case-sensitivity in sentry error grouping | +| 0.14.1 | 2024-01-24 | [\#34468](https://github.com/airbytehq/airbyte/pull/34468) | Add wait for process to be done before ending sync in destination BaseTDTest | +| 0.14.0 | 2024-01-23 | [\#34461](https://github.com/airbytehq/airbyte/pull/34461) | Revert non backward compatible signature changes from 0.13.1 | +| 0.13.3 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Denote if destinations fully support Destinations V2 | +| 0.13.2 | 2024-01-18 | [\#34364](https://github.com/airbytehq/airbyte/pull/34364) | Better logging in mongo db source connector | +| 0.13.1 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Add postCreateTable hook in destination JdbcSqlGenerator | +| 0.13.0 | 2024-01-16 | [\#34177](https://github.com/airbytehq/airbyte/pull/34177) | Add `useExpensiveSafeCasting` param in JdbcSqlGenerator methods; add JdbcTypingDedupingTest fixture; other DV2-related changes | +| 0.12.1 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Add hook for additional destination specific checks to JDBC destination check method | +| 0.12.0 | 2024-01-10 | [\#33875](https://github.com/airbytehq/airbyte/pull/33875) | Upgrade sshd-mina to 2.11.1 | +| 0.11.5 | 2024-01-10 | [\#34119](https://github.com/airbytehq/airbyte/pull/34119) | Remove wal2json support for postgres+debezium. | +| 0.11.4 | 2024-01-09 | [\#33305](https://github.com/airbytehq/airbyte/pull/33305) | Source stats in incremental syncs | +| 0.11.3 | 2023-01-09 | [\#33658](https://github.com/airbytehq/airbyte/pull/33658) | Always fail when debezium fails, even if it happened during the setup phase. | +| 0.11.2 | 2024-01-09 | [\#33969](https://github.com/airbytehq/airbyte/pull/33969) | Destination state stats implementation | +| 0.11.1 | 2024-01-04 | [\#33727](https://github.com/airbytehq/airbyte/pull/33727) | SSH bastion heartbeats for Destinations | +| 0.11.0 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | DV2 T+D uses Sql struct to represent transactions; other T+D-related changes | +| 0.10.4 | 2023-12-20 | [\#33071](https://github.com/airbytehq/airbyte/pull/33071) | Add the ability to parse JDBC parameters with another delimiter than '&' | +| 0.10.3 | 2024-01-03 | [\#33312](https://github.com/airbytehq/airbyte/pull/33312) | Send out count in AirbyteStateMessage | +| 0.10.1 | 2023-12-21 | [\#33723](https://github.com/airbytehq/airbyte/pull/33723) | Make memory-manager log message less scary | +| 0.10.0 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | JdbcDestinationHandler now properly implements `getInitialRawTableState`; reenable SqlGenerator test | +| 0.9.0 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation, exclude the T&D module from the CDK | +| 0.8.0 | 2023-12-18 | [\#33506](https://github.com/airbytehq/airbyte/pull/33506) | Improve async destination shutdown logic; more JDBC async migration work; improve DAT test schema handling | +| 0.7.9 | 2023-12-18 | [\#33549](https://github.com/airbytehq/airbyte/pull/33549) | Improve MongoDB logging. | +| 0.7.8 | 2023-12-18 | [\#33365](https://github.com/airbytehq/airbyte/pull/33365) | Emit stream statuses more consistently | +| 0.7.7 | 2023-12-18 | [\#33434](https://github.com/airbytehq/airbyte/pull/33307) | Remove LEGACY state | +| 0.7.6 | 2023-12-14 | [\#32328](https://github.com/airbytehq/airbyte/pull/33307) | Add schema less mode for mongodb CDC. Fixes for non standard mongodb id type. | +| 0.7.4 | 2023-12-13 | [\#33232](https://github.com/airbytehq/airbyte/pull/33232) | Track stream record count during sync; only run T+D if a stream had nonzero records or the previous sync left unprocessed records. | +| 0.7.3 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Extract shared JDBC T+D code. | +| 0.7.2 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | Fix DV2 JDBC type mappings (code changes in [\#33307](https://github.com/airbytehq/airbyte/pull/33307)). | +| 0.7.1 | 2023-12-01 | [\#33027](https://github.com/airbytehq/airbyte/pull/33027) | Add the abstract DB source debugger. | +| 0.7.0 | 2023-12-07 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Destinations V2 changes for JDBC destinations | +| 0.6.4 | 2023-12-06 | [\#33082](https://github.com/airbytehq/airbyte/pull/33082) | Improvements to schema snapshot error handling + schema snapshot history scope (scoped to configured DB). | +| 0.6.2 | 2023-11-30 | [\#32573](https://github.com/airbytehq/airbyte/pull/32573) | Update MSSQLConverter to enforce 6-digit microsecond precision for timestamp fields | +| 0.6.1 | 2023-11-30 | [\#32610](https://github.com/airbytehq/airbyte/pull/32610) | Support DB initial sync using binary as primary key. | +| 0.6.0 | 2023-11-30 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | JDBC destinations now use the async framework | +| 0.5.3 | 2023-11-28 | [\#32686](https://github.com/airbytehq/airbyte/pull/32686) | Better attribution of debezium engine shutdown due to heartbeat. | +| 0.5.1 | 2023-11-27 | [\#32662](https://github.com/airbytehq/airbyte/pull/32662) | Debezium initialization wait time will now read from initial setup time. | +| 0.5.0 | 2023-11-22 | [\#32656](https://github.com/airbytehq/airbyte/pull/32656) | Introduce TestDatabase test fixture, refactor database source test base classes. | +| 0.4.11 | 2023-11-14 | [\#32526](https://github.com/airbytehq/airbyte/pull/32526) | Clean up memory manager logs. | +| 0.4.10 | 2023-11-13 | [\#32285](https://github.com/airbytehq/airbyte/pull/32285) | Fix UUID codec ordering for MongoDB connector | +| 0.4.9 | 2023-11-13 | [\#32468](https://github.com/airbytehq/airbyte/pull/32468) | Further error grouping improvements for DV2 connectors | +| 0.4.8 | 2023-11-09 | [\#32377](https://github.com/airbytehq/airbyte/pull/32377) | source-postgres tests: skip dropping database | +| 0.4.7 | 2023-11-08 | [\#31856](https://github.com/airbytehq/airbyte/pull/31856) | source-postgres: support for infinity date and timestamps | +| 0.4.5 | 2023-11-07 | [\#32112](https://github.com/airbytehq/airbyte/pull/32112) | Async destinations framework: Allow configuring the queue flush threshold | +| 0.4.4 | 2023-11-06 | [\#32119](https://github.com/airbytehq/airbyte/pull/32119) | Add STANDARD UUID codec to MongoDB debezium handler | +| 0.4.2 | 2023-11-06 | [\#32190](https://github.com/airbytehq/airbyte/pull/32190) | Improve error deinterpolation | +| 0.4.1 | 2023-11-02 | [\#32192](https://github.com/airbytehq/airbyte/pull/32192) | Add 's3-destinations' CDK module. | +| 0.4.0 | 2023-11-02 | [\#32050](https://github.com/airbytehq/airbyte/pull/32050) | Fix compiler warnings. | +| 0.3.0 | 2023-11-02 | [\#31983](https://github.com/airbytehq/airbyte/pull/31983) | Add deinterpolation feature to AirbyteExceptionHandler. | +| 0.2.4 | 2023-10-31 | [\#31807](https://github.com/airbytehq/airbyte/pull/31807) | Handle case of debezium update and delete of records in mongodb. | +| 0.2.3 | 2023-10-31 | [\#32022](https://github.com/airbytehq/airbyte/pull/32022) | Update Debezium version from 2.20 -> 2.4.0. | +| 0.2.2 | 2023-10-31 | [\#31976](https://github.com/airbytehq/airbyte/pull/31976) | Debezium tweaks to make tests run faster. | +| 0.2.0 | 2023-10-30 | [\#31960](https://github.com/airbytehq/airbyte/pull/31960) | Hoist top-level gradle subprojects into CDK. | +| 0.1.12 | 2023-10-24 | [\#31674](https://github.com/airbytehq/airbyte/pull/31674) | Fail sync when Debezium does not shut down properly. | +| 0.1.11 | 2023-10-18 | [\#31486](https://github.com/airbytehq/airbyte/pull/31486) | Update constants in AdaptiveSourceRunner. | +| 0.1.9 | 2023-10-12 | [\#31309](https://github.com/airbytehq/airbyte/pull/31309) | Use toPlainString() when handling BigDecimals in PostgresConverter | +| 0.1.8 | 2023-10-11 | [\#31322](https://github.com/airbytehq/airbyte/pull/31322) | Cap log line length to 32KB to prevent loss of records | +| 0.1.7 | 2023-10-10 | [\#31194](https://github.com/airbytehq/airbyte/pull/31194) | Deallocate unused per stream buffer memory when empty | +| 0.1.6 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | +| 0.1.5 | 2023-10-09 | [\#31196](https://github.com/airbytehq/airbyte/pull/31196) | Update typo in CDK (CDN_LSN -> CDC_LSN) | +| 0.1.4 | 2023-10-06 | [\#31139](https://github.com/airbytehq/airbyte/pull/31139) | Reduce async buffer | +| 0.1.1 | 2023-09-28 | [\#30835](https://github.com/airbytehq/airbyte/pull/30835) | JDBC destinations now avoid staging area name collisions by using the raw table name as the stage name. (previously we used the stream name as the stage name) | +| 0.1.0 | 2023-09-27 | [\#30445](https://github.com/airbytehq/airbyte/pull/30445) | First launch, including shared classes for all connectors. | +| 0.0.2 | 2023-08-21 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Version bump only (no other changes). | +| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | \ No newline at end of file diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConnectorExceptionUtil.java b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConnectorExceptionUtil.java index 9f4ae86cfe78..dc49697d3e99 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConnectorExceptionUtil.java +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/util/ConnectorExceptionUtil.java @@ -10,6 +10,7 @@ import io.airbyte.cdk.integrations.base.errors.messages.ErrorMessage; import io.airbyte.commons.exceptions.ConfigErrorException; import io.airbyte.commons.exceptions.ConnectionErrorException; +import io.airbyte.commons.functional.Either; import java.sql.SQLException; import java.sql.SQLSyntaxErrorException; import java.util.Collection; @@ -85,6 +86,17 @@ public static void logAllAndThrowFirst(final String initia } } + public static List getResultsOrLogAndThrowFirst(final String initialMessage, + final List> eithers) + throws T { + List throwables = eithers.stream().filter(Either::isLeft).map(Either::getLeft).toList(); + if (!throwables.isEmpty()) { + logAllAndThrowFirst(initialMessage, throwables); + } + // No need to filter on isRight since isLeft will throw before reaching this line. + return eithers.stream().map(Either::getRight).toList(); + } + private static boolean isConfigErrorException(Throwable e) { return e instanceof ConfigErrorException; } diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties index 1df5d31312c9..4433e215f812 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties @@ -1 +1 @@ -version=0.22.1 +version=0.23.0 diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java index f43e1abdea05..c060133a5546 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java @@ -252,9 +252,7 @@ private void assertCustomParametersDontOverwriteDefaultParameters(final Map destinationHandler = getDestinationHandler(databaseName, database); + final DestinationHandler destinationHandler = getDestinationHandler(databaseName, database); final boolean disableTypeDedupe = !config.has(DISABLE_TYPE_DEDUPE) || config.get(DISABLE_TYPE_DEDUPE).asBoolean(false); final TyperDeduper typerDeduper; if (disableTypeDedupe) { - typerDeduper = new NoOpTyperDeduperWithV1V2Migrations<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator); + typerDeduper = new NoOpTyperDeduperWithV1V2Migrations(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator); } else { typerDeduper = - new DefaultTyperDeduper<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator); + new DefaultTyperDeduper(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator); } return typerDeduper; } diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/ColumnDefinition.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/ColumnDefinition.java index 68e715d2cbb2..fe41101366c2 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/ColumnDefinition.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/ColumnDefinition.java @@ -4,8 +4,13 @@ package io.airbyte.cdk.integrations.destination.jdbc; -import java.sql.SQLType; - -public record ColumnDefinition(String name, String type, SQLType sqlType, int columnSize) { +/** + * Jdbc destination column definition representation + * + * @param name + * @param type + * @param columnSize + */ +public record ColumnDefinition(String name, String type, int columnSize, boolean isNullable) { } diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/CustomSqlType.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/CustomSqlType.java deleted file mode 100644 index dad853bb8e08..000000000000 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/CustomSqlType.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cdk.integrations.destination.jdbc; - -import java.sql.SQLType; - -/** - * Custom SqlType definition when there is no mapping in {@link java.sql.JDBCType} - * - * @param name - * @param vendor - * @param vendorTypeNumber - */ -public record CustomSqlType(String name, String vendor, Integer vendorTypeNumber) implements SQLType { - - @Override - public String getName() { - return name; - } - - @Override - public String getVendor() { - return vendor; - } - - @Override - public Integer getVendorTypeNumber() { - return vendorTypeNumber; - } - -} diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableDefinition.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableDefinition.java index 353d6d03cb44..c8fc4f2e7ca8 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableDefinition.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableDefinition.java @@ -7,7 +7,7 @@ import java.util.LinkedHashMap; /** - * Jdbc destination table definition representation + * Jdbc destination table definition representation with a map of column names to column definitions * * @param columns */ diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableSchemaRecordSet.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableSchemaRecordSet.java deleted file mode 100644 index f87d57218c48..000000000000 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TableSchemaRecordSet.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cdk.integrations.destination.jdbc; - -public record TableSchemaRecordSet() { - -} diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TypeInfoRecordSet.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TypeInfoRecordSet.java deleted file mode 100644 index 2ef35e795b24..000000000000 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/TypeInfoRecordSet.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cdk.integrations.destination.jdbc; - -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.util.LinkedHashMap; - -/** - * A record representing the {@link java.sql.ResultSet} returned by calling - * {@link DatabaseMetaData#getTypeInfo()} - *

- * See that method for a better description of the parameters to this record - */ -public record TypeInfoRecordSet( - String typeName, - int dataType, - int precision, - String literalPrefix, - String literalSuffix, - String createParams, - short nullable, - boolean caseSensitive, - short searchable, - boolean unsignedAttribute, - boolean fixedPrecScale, - boolean autoIncrement, - String localTypeName, - short minimumScale, - short maximumScale, - - // Unused - int sqlDataType, - - // Unused - int sqlDatetimeSub, - int numPrecRadix) { - - public static LinkedHashMap getTypeInfoList(final DatabaseMetaData databaseMetaData) throws Exception { - final LinkedHashMap types = new LinkedHashMap<>(); - try (final ResultSet rs = databaseMetaData.getTypeInfo()) { - while (rs.next()) { - final var typeName = rs.getString("TYPE_NAME"); - types.put(typeName, - new TypeInfoRecordSet( - typeName, - rs.getInt("DATA_TYPE"), - rs.getInt("PRECISION"), - rs.getString("LITERAL_PREFIX"), - rs.getString("LITERAL_SUFFIX"), - rs.getString("CREATE_PARAMS"), - rs.getShort("NULLABLE"), - rs.getBoolean("CASE_SENSITIVE"), - rs.getShort("SEARCHABLE"), - rs.getBoolean("UNSIGNED_ATTRIBUTE"), - rs.getBoolean("FIXED_PREC_SCALE"), - rs.getBoolean("AUTO_INCREMENT"), - rs.getString("LOCAL_TYPE_NAME"), - rs.getShort("MINIMUM_SCALE"), - rs.getShort("MAXIMUM_SCALE"), - rs.getInt("SQL_DATA_TYPE"), - rs.getInt("SQL_DATETIME_SUB"), - rs.getInt("NUM_PREC_RADIX"))); - } - } - return types; - } - -} diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcDestinationHandler.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcDestinationHandler.java index 26a50e6586e5..1aa0b687f8c5 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcDestinationHandler.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcDestinationHandler.java @@ -4,6 +4,10 @@ package io.airbyte.cdk.integrations.destination.jdbc.typing_deduping; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_META; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_RAW_ID; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.V2_FINAL_TABLE_METADATA_COLUMNS; import static org.jooq.impl.DSL.exists; import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.name; @@ -12,16 +16,23 @@ import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.integrations.destination.jdbc.ColumnDefinition; -import io.airbyte.cdk.integrations.destination.jdbc.CustomSqlType; import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; +import io.airbyte.cdk.integrations.util.ConnectorExceptionUtil; +import io.airbyte.commons.concurrency.CompletableFutures; import io.airbyte.commons.exceptions.SQLRuntimeException; +import io.airbyte.commons.functional.Either; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; import io.airbyte.integrations.base.destination.typing_deduping.DestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialState; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialStateImpl; +import io.airbyte.integrations.base.destination.typing_deduping.InitialRawTableState; import io.airbyte.integrations.base.destination.typing_deduping.Sql; +import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig; import io.airbyte.integrations.base.destination.typing_deduping.StreamId; -import java.sql.JDBCType; +import io.airbyte.integrations.base.destination.typing_deduping.Struct; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.SQLType; import java.sql.Timestamp; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -30,6 +41,8 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; import org.jooq.conf.ParamType; @@ -38,7 +51,7 @@ import org.slf4j.LoggerFactory; @Slf4j -public class JdbcDestinationHandler implements DestinationHandler { +public abstract class JdbcDestinationHandler implements DestinationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(JdbcDestinationHandler.class); @@ -51,18 +64,11 @@ public JdbcDestinationHandler(final String databaseName, this.jdbcDatabase = jdbcDatabase; } - @Override - public Optional findExistingTable(final StreamId id) throws Exception { + private Optional findExistingTable(final StreamId id) throws Exception { return findExistingTable(jdbcDatabase, databaseName, id.finalNamespace(), id.finalName()); } - @Override - public LinkedHashMap findExistingFinalTables(List streamIds) throws Exception { - return null; - } - - @Override - public boolean isFinalTableEmpty(final StreamId id) throws Exception { + private boolean isFinalTableEmpty(final StreamId id) throws Exception { return !jdbcDatabase.queryBoolean( select( field(exists( @@ -72,8 +78,7 @@ public boolean isFinalTableEmpty(final StreamId id) throws Exception { .getSQL(ParamType.INLINED)); } - @Override - public InitialRawTableState getInitialRawTableState(final StreamId id) throws Exception { + private InitialRawTableState getInitialRawTableState(final StreamId id) throws Exception { boolean tableExists = jdbcDatabase.executeMetadataQuery(dbmetadata -> { LOGGER.info("Retrieving table from Db metadata: {} {} {}", databaseName, id.rawNamespace(), id.rawName()); try (final ResultSet table = dbmetadata.getTables(databaseName, id.rawNamespace(), id.rawName(), null)) { @@ -143,6 +148,39 @@ public void execute(final Sql sql) throws Exception { } } + @Override + public List gatherInitialState(List streamConfigs) throws Exception { + final List> initialStates = streamConfigs.stream() + .map(this::retrieveState) + .toList(); + final List> states = CompletableFutures.allOf(initialStates).toCompletableFuture().join(); + return ConnectorExceptionUtil.getResultsOrLogAndThrowFirst("Failed to retrieve initial state", states); + } + + private CompletionStage retrieveState(final StreamConfig streamConfig) { + return CompletableFuture.supplyAsync(() -> { + try { + final Optional finalTableDefinition = findExistingTable(streamConfig.id()); + final boolean isSchemaMismatch; + final boolean isFinalTableEmpty; + if (finalTableDefinition.isPresent()) { + isSchemaMismatch = !existingSchemaMatchesStreamConfig(streamConfig, finalTableDefinition.get()); + isFinalTableEmpty = isFinalTableEmpty(streamConfig.id()); + } else { + // If the final table doesn't exist, then by definition it doesn't have a schema mismatch and has no + // records. + isSchemaMismatch = false; + isFinalTableEmpty = true; + } + final InitialRawTableState initialRawTableState = getInitialRawTableState(streamConfig.id()); + return new DestinationInitialStateImpl(streamConfig, finalTableDefinition.isPresent(), initialRawTableState, + isSchemaMismatch, isFinalTableEmpty); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + public static Optional findExistingTable(final JdbcDatabase jdbcDatabase, final String databaseName, final String schemaName, @@ -159,16 +197,8 @@ public static Optional findExistingTable(final JdbcDatabase jdb final String columnName = columns.getString("COLUMN_NAME"); final String typeName = columns.getString("TYPE_NAME"); final int columnSize = columns.getInt("COLUMN_SIZE"); - final int datatype = columns.getInt("DATA_TYPE"); - SQLType sqlType; - try { - sqlType = JDBCType.valueOf(datatype); - } catch (final IllegalArgumentException e) { - // Unknown jdbcType convert to customSqlType - LOGGER.warn("Unrecognized JDBCType {}; falling back to UNKNOWN", datatype, e); - sqlType = new CustomSqlType("Unknown", "Unknown", datatype); - } - columnDefinitions.put(columnName, new ColumnDefinition(columnName, typeName, sqlType, columnSize)); + final String isNullable = columns.getString("IS_NULLABLE"); + columnDefinitions.put(columnName, new ColumnDefinition(columnName, typeName, columnSize, fromIsNullableIsoString(isNullable))); } } catch (final SQLException e) { LOGGER.error("Failed to retrieve column info for {}.{}.{}", databaseName, schemaName, tableName, e); @@ -184,4 +214,55 @@ public static Optional findExistingTable(final JdbcDatabase jdb return Optional.of(new TableDefinition(retrievedColumnDefns)); } + public static boolean fromIsNullableIsoString(final String isNullable) { + return "YES".equalsIgnoreCase(isNullable); + } + + private boolean isAirbyteRawIdColumnMatch(final TableDefinition existingTable) { + return existingTable.columns().containsKey(COLUMN_NAME_AB_RAW_ID) && + toJdbcTypeName(AirbyteProtocolType.STRING).equals(existingTable.columns().get(COLUMN_NAME_AB_RAW_ID).type()); + } + + private boolean isAirbyteExtractedAtColumnMatch(final TableDefinition existingTable) { + return existingTable.columns().containsKey(COLUMN_NAME_AB_EXTRACTED_AT) && + toJdbcTypeName(AirbyteProtocolType.TIMESTAMP_WITH_TIMEZONE).equals(existingTable.columns().get(COLUMN_NAME_AB_EXTRACTED_AT).type()); + } + + private boolean isAirbyteMetaColumnMatch(final TableDefinition existingTable) { + return existingTable.columns().containsKey(COLUMN_NAME_AB_META) && + toJdbcTypeName(new Struct(new LinkedHashMap<>())).equals(existingTable.columns().get(COLUMN_NAME_AB_META).type()); + } + + protected boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final TableDefinition existingTable) { + // Check that the columns match, with special handling for the metadata columns. + if (!isAirbyteRawIdColumnMatch(existingTable) || + !isAirbyteExtractedAtColumnMatch(existingTable) || + !isAirbyteMetaColumnMatch(existingTable)) { + // Missing AB meta columns from final table, we need them to do proper T+D so trigger soft-reset + return false; + } + final LinkedHashMap intendedColumns = stream.columns().entrySet().stream() + .collect(LinkedHashMap::new, + (map, column) -> map.put(column.getKey().name(), toJdbcTypeName(column.getValue())), + LinkedHashMap::putAll); + + // Filter out Meta columns since they don't exist in stream config. + final LinkedHashMap actualColumns = existingTable.columns().entrySet().stream() + .filter(column -> V2_FINAL_TABLE_METADATA_COLUMNS.stream() + .noneMatch(airbyteColumnName -> airbyteColumnName.equals(column.getKey()))) + .collect(LinkedHashMap::new, + (map, column) -> map.put(column.getKey(), column.getValue().type()), + LinkedHashMap::putAll); + + return actualColumns.equals(intendedColumns); + } + + /** + * Convert to the TYPE_NAME retrieved from {@link java.sql.DatabaseMetaData#getColumns} + * + * @param airbyteType + * @return + */ + protected abstract String toJdbcTypeName(final AirbyteType airbyteType); + } diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcSqlGenerator.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcSqlGenerator.java index ec6fab26772d..d32a84de478e 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcSqlGenerator.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/JdbcSqlGenerator.java @@ -29,7 +29,6 @@ import com.google.common.annotations.VisibleForTesting; import io.airbyte.cdk.integrations.destination.NamingConventionTransformer; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; import io.airbyte.integrations.base.destination.typing_deduping.Array; @@ -66,7 +65,7 @@ import org.jooq.impl.DSL; import org.jooq.impl.SQLDataType; -public abstract class JdbcSqlGenerator implements SqlGenerator { +public abstract class JdbcSqlGenerator implements SqlGenerator { protected static final String ROW_NUMBER_COLUMN_NAME = "row_number"; private static final String TYPING_CTE_ALIAS = "intermediate_data"; diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt index 17447dbf0833..5c9963f5bad8 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/typing_deduping/RawOnlySqlGenerator.kt @@ -56,11 +56,4 @@ class RawOnlySqlGenerator(private val namingTransformer: NamingConventionTransfo ): Field? { throw NotImplementedError("This Destination does not support final tables") } - - override fun existingSchemaMatchesStreamConfig( - stream: StreamConfig, - existingTable: TableDefinition - ): Boolean { - throw NotImplementedError("This Destination does not support final tables") - } } diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/test/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestinationTest.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/test/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestinationTest.java index f532b8ba8766..a5a07903ad48 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/test/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestinationTest.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/test/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestinationTest.java @@ -9,8 +9,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableMap; +import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.db.jdbc.JdbcUtils; import io.airbyte.cdk.integrations.destination.StandardNameTransformer; +import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.commons.exceptions.ConfigErrorException; import io.airbyte.commons.json.Jsons; @@ -139,6 +141,11 @@ protected JdbcSqlGenerator getSqlGenerator() { return null; } + @Override + protected JdbcDestinationHandler getDestinationHandler(String databaseName, JdbcDatabase database) { + return null; + } + } } diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/typing_deduping/JdbcSqlGeneratorIntegrationTest.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/typing_deduping/JdbcSqlGeneratorIntegrationTest.java index a71711cf17c4..df4ca42e004b 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/typing_deduping/JdbcSqlGeneratorIntegrationTest.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/testFixtures/java/io/airbyte/cdk/integrations/standardtest/destination/typing_deduping/JdbcSqlGeneratorIntegrationTest.java @@ -18,7 +18,6 @@ import com.fasterxml.jackson.databind.JsonNode; import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.integrations.base.JavaBaseConstants; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; import io.airbyte.integrations.base.destination.typing_deduping.BaseSqlGeneratorIntegrationTest; @@ -37,7 +36,7 @@ import org.jooq.impl.DSL; import org.jooq.impl.SQLDataType; -public abstract class JdbcSqlGeneratorIntegrationTest extends BaseSqlGeneratorIntegrationTest { +public abstract class JdbcSqlGeneratorIntegrationTest extends BaseSqlGeneratorIntegrationTest { protected abstract JdbcDatabase getDatabase(); diff --git a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/concurrency/CompletableFutures.java b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/concurrency/CompletableFutures.java index 7e17307fa9d0..d7330332ca57 100644 --- a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/concurrency/CompletableFutures.java +++ b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/concurrency/CompletableFutures.java @@ -4,25 +4,55 @@ package io.airbyte.commons.concurrency; +import io.airbyte.commons.functional.Either; +import java.lang.reflect.Array; +import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.atomic.AtomicInteger; public class CompletableFutures { /** - * Utility method which blocks until all futures are complete. Returns a list of the results of all - * futures. + * Non-blocking implementation which does not use join. and returns an aggregated future. The order + * of results is preserved from the original list of futures. * - * @param futures - * @return - * @param + * @param futures list of futures + * @param type of result + * @return a future that completes when all the input futures have completed */ - public static List allOf(final List> futures) { - // return CompletableFuture - // .allOf(futures.toArray(new CompletableFuture[0])) - // .thenApply(v -> futures.stream().map(CompletableFuture::join).toList()) - // .join(); - return null; + public static CompletionStage>> allOf(final List> futures) { + CompletableFuture>> result = new CompletableFuture<>(); + final int size = futures.size(); + final AtomicInteger counter = new AtomicInteger(); + @SuppressWarnings("unchecked") + final Either[] results = (Either[]) Array.newInstance(Either.class, size); + // attach a whenComplete to all futures + for (int i = 0; i < size; i++) { + final int currentIndex = i; + futures.get(i).whenComplete((value, exception) -> { + // if exception is null, then the future completed successfully + // maybe synchronization is unnecessary here, but it's better to be safe + synchronized (results) { + if (exception == null) { + results[currentIndex] = Either.right(value); + } else { + if (exception instanceof Exception) { + results[currentIndex] = Either.left((Exception) exception); + } else { + // this should never happen + throw new RuntimeException("Unexpected exception in a future completion.", exception); + } + } + } + int completedCount = counter.incrementAndGet(); + if (completedCount == size) { + result.complete(Arrays.asList(results)); + } + }); + } + return result; } } diff --git a/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/functional/Either.java b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/functional/Either.java new file mode 100644 index 000000000000..187b109e42f2 --- /dev/null +++ b/airbyte-cdk/java/airbyte-cdk/dependencies/src/main/java/io/airbyte/commons/functional/Either.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.commons.functional; + +import java.util.Objects; + +/** + * A class that represents a value of one of two possible types (a disjoint union). An instance of + * Either is an instance of Left or Right. + * + * A common use of Either is for error handling in functional programming. By convention, Left is + * failure and Right is success. + * + * @param the type of the left value + * @param the type of the right value + */ +public class Either { + + private final Error left; + private final Result right; + + private Either(Error left, Result right) { + this.left = left; + this.right = right; + } + + public boolean isLeft() { + return left != null; + } + + public boolean isRight() { + return right != null; + } + + public Error getLeft() { + return left; + } + + public Result getRight() { + return right; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Either either = (Either) o; + return Objects.equals(left, either.left) && Objects.equals(right, either.right); + } + + @Override + public int hashCode() { + return Objects.hash(left, right); + } + + public static Either left(Error error) { + return new Either<>(error, null); + } + + public static Either right(Result result) { + return new Either<>(null, result); + } + +} diff --git a/airbyte-cdk/java/airbyte-cdk/dependencies/src/test/java/io/airbyte/commons/concurrency/CompletableFuturesTest.java b/airbyte-cdk/java/airbyte-cdk/dependencies/src/test/java/io/airbyte/commons/concurrency/CompletableFuturesTest.java new file mode 100644 index 000000000000..def67f8e5916 --- /dev/null +++ b/airbyte-cdk/java/airbyte-cdk/dependencies/src/test/java/io/airbyte/commons/concurrency/CompletableFuturesTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.commons.concurrency; + +import static org.junit.jupiter.api.Assertions.*; + +import io.airbyte.commons.functional.Either; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import org.junit.jupiter.api.Test; + +class CompletableFuturesTest { + + @Test + public void testAllOf() { + // Complete in random order + final List> futures = Arrays.asList( + returnSuccessWithDelay(1, 2000), + returnSuccessWithDelay(2, 200), + returnSuccessWithDelay(3, 500), + returnSuccessWithDelay(4, 100), + returnFailureWithDelay("Fail 5", 2000), + returnFailureWithDelay("Fail 6", 300)); + + final CompletableFuture>> allOfResult = CompletableFutures.allOf(futures).toCompletableFuture(); + final List> result = allOfResult.join(); + List> success = result.stream().filter(Either::isRight).toList(); + assertEquals(success, Arrays.asList( + Either.right(1), + Either.right(2), + Either.right(3), + Either.right(4))); + // Extract wrapped CompletionException messages. + final List failureMessages = result.stream().filter(Either::isLeft).map(either -> either.getLeft().getCause().getMessage()).toList(); + assertEquals(failureMessages, Arrays.asList("Fail 5", "Fail 6")); + } + + private CompletableFuture returnSuccessWithDelay(final int value, final long delayMs) { + return CompletableFuture.supplyAsync(() -> { + try { + Thread.sleep(delayMs); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return value; + }); + } + + private CompletableFuture returnFailureWithDelay(final String message, final long delayMs) { + return CompletableFuture.supplyAsync(() -> { + try { + Thread.sleep(delayMs); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + throw new RuntimeException(message); + }); + } + +} diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/BaseDestinationV1V2Migrator.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/BaseDestinationV1V2Migrator.java index a33c3b715630..95c5841241b7 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/BaseDestinationV1V2Migrator.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/BaseDestinationV1V2Migrator.java @@ -13,14 +13,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class BaseDestinationV1V2Migrator implements DestinationV1V2Migrator { +public abstract class BaseDestinationV1V2Migrator implements DestinationV1V2Migrator { protected static final Logger LOGGER = LoggerFactory.getLogger(BaseDestinationV1V2Migrator.class); @Override public void migrateIfNecessary( - final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final StreamConfig streamConfig) throws Exception { LOGGER.info("Assessing whether migration is necessary for stream {}", streamConfig.id().finalName()); @@ -59,8 +59,8 @@ protected boolean shouldMigrate(final StreamConfig streamConfig) throws Exceptio * @param destinationHandler the class which executes the sql statements * @param streamConfig the stream to migrate the raw table of */ - public void migrate(final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + public void migrate(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final StreamConfig streamConfig) throws TableNotMigratedException { final var namespacedTableName = convertToV1RawName(streamConfig); diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParser.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParser.java index 925d5037ea28..372f2999be64 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParser.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParser.java @@ -23,14 +23,14 @@ public class CatalogParser { private static final Logger LOGGER = LoggerFactory.getLogger(CatalogParser.class); - private final SqlGenerator sqlGenerator; + private final SqlGenerator sqlGenerator; private final String rawNamespace; - public CatalogParser(final SqlGenerator sqlGenerator) { + public CatalogParser(final SqlGenerator sqlGenerator) { this(sqlGenerator, DEFAULT_AIRBYTE_INTERNAL_NAMESPACE); } - public CatalogParser(final SqlGenerator sqlGenerator, final String rawNamespace) { + public CatalogParser(final SqlGenerator sqlGenerator, final String rawNamespace) { this.sqlGenerator = sqlGenerator; this.rawNamespace = rawNamespace; } diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java index 764f888c4e16..ec49be79cb57 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduper.java @@ -5,19 +5,24 @@ package io.airbyte.integrations.base.destination.typing_deduping; import static io.airbyte.cdk.integrations.base.IntegrationRunner.TYPE_AND_DEDUPE_THREAD_NAME; -import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.getCountOfTypeAndDedupeThreads; +import static io.airbyte.cdk.integrations.util.ConnectorExceptionUtil.getResultsOrLogAndThrowFirst; +import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.*; import static io.airbyte.integrations.base.destination.typing_deduping.FutureUtils.reduceExceptions; import static io.airbyte.integrations.base.destination.typing_deduping.TyperDeduperUtilKt.prepareAllSchemas; import static java.util.Collections.singleton; import io.airbyte.cdk.integrations.destination.StreamSyncSummary; +import io.airbyte.commons.concurrency.CompletableFutures; +import io.airbyte.commons.functional.Either; import io.airbyte.protocol.models.v0.DestinationSyncMode; import io.airbyte.protocol.models.v0.StreamDescriptor; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -45,22 +50,22 @@ * Note that #prepareTables() initializes some internal state. The other methods will throw an * exception if that method was not called. */ -public class DefaultTyperDeduper implements TyperDeduper { +public class DefaultTyperDeduper implements TyperDeduper { private static final Logger LOGGER = LoggerFactory.getLogger(TyperDeduper.class); private static final String NO_SUFFIX = ""; private static final String TMP_OVERWRITE_TABLE_SUFFIX = "_airbyte_tmp"; - private final SqlGenerator sqlGenerator; - private final DestinationHandler destinationHandler; + private final SqlGenerator sqlGenerator; + private final DestinationHandler destinationHandler; - private final DestinationV1V2Migrator v1V2Migrator; + private final DestinationV1V2Migrator v1V2Migrator; private final V2TableMigrator v2TableMigrator; private final ParsedCatalog parsedCatalog; private Set overwriteStreamsWithTmpTable; private final Set> streamsWithSuccessfulSetup; - private final Map initialRawTableStateByStream; + private final Map initialRawTableStateByStream; // We only want to run a single instance of T+D per stream at a time. These objects are used for // synchronization per stream. // Use a read-write lock because we need the same semantics: @@ -74,10 +79,10 @@ public class DefaultTyperDeduper implements TyperDeduper private final ExecutorService executorService; - public DefaultTyperDeduper(final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + public DefaultTyperDeduper(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final ParsedCatalog parsedCatalog, - final DestinationV1V2Migrator v1V2Migrator, + final DestinationV1V2Migrator v1V2Migrator, final V2TableMigrator v2TableMigrator) { this.sqlGenerator = sqlGenerator; this.destinationHandler = destinationHandler; @@ -92,12 +97,10 @@ public DefaultTyperDeduper(final SqlGenerator sqlGenerat new BasicThreadFactory.Builder().namingPattern(TYPE_AND_DEDUPE_THREAD_NAME).build()); } - public DefaultTyperDeduper( - final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + public DefaultTyperDeduper(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final ParsedCatalog parsedCatalog, - final DestinationV1V2Migrator v1V2Migrator, - final int defaultThreadCount) { + final DestinationV1V2Migrator v1V2Migrator) { this(sqlGenerator, destinationHandler, parsedCatalog, v1V2Migrator, new NoopV2TableMigrator()); } @@ -113,31 +116,45 @@ public void prepareTables() throws Exception { overwriteStreamsWithTmpTable = ConcurrentHashMap.newKeySet(); LOGGER.info("Preparing tables"); + // This is intentionally not done in parallel to avoid rate limits in some destinations. prepareSchemas(parsedCatalog); - final Set>> prepareTablesTasks = new HashSet<>(); - for (final StreamConfig stream : parsedCatalog.streams()) { - prepareTablesTasks.add(prepareTablesFuture(stream)); - } - CompletableFuture.allOf(prepareTablesTasks.toArray(CompletableFuture[]::new)).join(); - reduceExceptions(prepareTablesTasks, "The following exceptions were thrown attempting to prepare tables:\n"); + + // TODO: Either the migrations run the soft reset and create v2 tables or the actual prepare tables. + // unify the logic with current state of raw tables & final tables. This is done first before gather + // initial state to avoid recreating final tables later again. + final List> runMigrationsResult = + CompletableFutures.allOf(parsedCatalog.streams().stream().map(this::runMigrationsAsync).toList()).toCompletableFuture().join(); + getResultsOrLogAndThrowFirst("The following exceptions were thrown attempting to run migrations:\n", runMigrationsResult); + final List initialStates = destinationHandler.gatherInitialState(parsedCatalog.streams()); + final List> prepareTablesFutureResult = CompletableFutures.allOf( + initialStates.stream().map(this::prepareTablesFuture).toList()).toCompletableFuture().join(); + getResultsOrLogAndThrowFirst("The following exceptions were thrown attempting to prepare tables:\n", prepareTablesFutureResult); } - private CompletableFuture> prepareTablesFuture(final StreamConfig stream) { + private CompletionStage runMigrationsAsync(StreamConfig streamConfig) { + return CompletableFuture.runAsync(() -> { + try { + // Migrate the Raw Tables if this is the first v2 sync after a v1 sync + v1V2Migrator.migrateIfNecessary(sqlGenerator, destinationHandler, streamConfig); + v2TableMigrator.migrateIfNecessary(streamConfig); + } catch (Exception e) { + throw new RuntimeException(e); + } + }, this.executorService); + } + + private CompletionStage prepareTablesFuture(final DestinationInitialState initialState) { // For each stream, make sure that its corresponding final table exists. // Also, for OVERWRITE streams, decide if we're writing directly to the final table, or into an // _airbyte_tmp table. return CompletableFuture.supplyAsync(() -> { + final var stream = initialState.streamConfig(); try { - // Migrate the Raw Tables if this is the first v2 sync after a v1 sync - v1V2Migrator.migrateIfNecessary(sqlGenerator, destinationHandler, stream); - v2TableMigrator.migrateIfNecessary(stream); - - final Optional existingTable = destinationHandler.findExistingTable(stream.id()); - if (existingTable.isPresent()) { + if (initialState.isFinalTablePresent()) { LOGGER.info("Final Table exists for stream {}", stream.id().finalName()); // The table already exists. Decide whether we're writing to it directly, or using a tmp table. if (stream.destinationSyncMode() == DestinationSyncMode.OVERWRITE) { - if (!destinationHandler.isFinalTableEmpty(stream.id()) || !sqlGenerator.existingSchemaMatchesStreamConfig(stream, existingTable.get())) { + if (!initialState.isFinalTableEmpty() || initialState.isSchemaMismatch()) { // We want to overwrite an existing table. Write into a tmp table. We'll overwrite the table at the // end of the sync. overwriteStreamsWithTmpTable.add(stream.id()); @@ -149,7 +166,7 @@ private CompletableFuture> prepareTablesFuture(final StreamC stream.id().finalName()); } - } else if (!sqlGenerator.existingSchemaMatchesStreamConfig(stream, existingTable.get())) { + } else if (initialState.isSchemaMismatch()) { // We're loading data directly into the existing table. Make sure it has the right schema. TypeAndDedupeTransaction.executeSoftReset(sqlGenerator, destinationHandler, stream); } @@ -158,8 +175,8 @@ private CompletableFuture> prepareTablesFuture(final StreamC // The table doesn't exist. Create it. Don't force. destinationHandler.execute(sqlGenerator.createTable(stream, NO_SUFFIX, false)); } - final DestinationHandler.InitialRawTableState initialRawTableState = destinationHandler.getInitialRawTableState(stream.id()); - initialRawTableStateByStream.put(stream.id(), initialRawTableState); + + initialRawTableStateByStream.put(stream.id(), initialState.initialRawTableState()); streamsWithSuccessfulSetup.add(Pair.of(stream.id().originalNamespace(), stream.id().originalName())); @@ -172,10 +189,10 @@ private CompletableFuture> prepareTablesFuture(final StreamC // immediately acquire the lock. internalTdLocks.put(stream.id(), new ReentrantLock()); - return Optional.empty(); + return null; } catch (final Exception e) { LOGGER.error("Exception occurred while preparing tables for stream " + stream.id().originalName(), e); - return Optional.of(e); + throw new RuntimeException(e); } }, this.executorService); } @@ -235,7 +252,7 @@ public CompletableFuture> typeAndDedupeTask(final StreamConf final Lock externalLock = tdLocks.get(streamConfig.id()).writeLock(); externalLock.lock(); try { - final DestinationHandler.InitialRawTableState initialRawTableState = initialRawTableStateByStream.get(streamConfig.id()); + final InitialRawTableState initialRawTableState = initialRawTableStateByStream.get(streamConfig.id()); TypeAndDedupeTransaction.executeTypeAndDedupe( sqlGenerator, destinationHandler, diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationHandler.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationHandler.java index c2fb545f318d..f75f0fc9a040 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationHandler.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationHandler.java @@ -4,37 +4,12 @@ package io.airbyte.integrations.base.destination.typing_deduping; -import java.time.Instant; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Optional; -public interface DestinationHandler { - - Optional findExistingTable(StreamId id) throws Exception; - - /** - * Given a list of stream ids, return a map of stream ids to existing tables. If the table is - * missing, the key should not be present in the map. - * - * @param streamIds - * @return - * @throws Exception - */ - LinkedHashMap findExistingFinalTables(List streamIds) throws Exception; - - boolean isFinalTableEmpty(StreamId id) throws Exception; - - /** - * Returns the highest timestamp such that all records with _airbyte_extracted equal to or earlier - * than that timestamp have non-null _airbyte_loaded_at. - *

- * If the raw table is empty or does not exist, return an empty optional. - */ - InitialRawTableState getInitialRawTableState(StreamId id) throws Exception; - - record InitialRawTableState(boolean hasUnprocessedRecords, Optional maxProcessedTimestamp) {} +public interface DestinationHandler { void execute(final Sql sql) throws Exception; + List gatherInitialState(List streamConfigs) throws Exception; + } diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialState.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialState.java new file mode 100644 index 000000000000..31aa25770790 --- /dev/null +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialState.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.base.destination.typing_deduping; + +/** + * Interface representing the initial state of a destination table. + * + */ +public interface DestinationInitialState { + + StreamConfig streamConfig(); + + boolean isFinalTablePresent(); + + InitialRawTableState initialRawTableState(); + + boolean isSchemaMismatch(); + + boolean isFinalTableEmpty(); + +} diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialStateImpl.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialStateImpl.java new file mode 100644 index 000000000000..e1fa315c703e --- /dev/null +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationInitialStateImpl.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.base.destination.typing_deduping; + +public record DestinationInitialStateImpl(StreamConfig streamConfig, + boolean isFinalTablePresent, + InitialRawTableState initialRawTableState, + boolean isSchemaMismatch, + boolean isFinalTableEmpty) + implements DestinationInitialState { + +} diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2Migrator.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2Migrator.java index 7e28906673a6..5e1e26e804f1 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2Migrator.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2Migrator.java @@ -4,7 +4,7 @@ package io.airbyte.integrations.base.destination.typing_deduping; -public interface DestinationV1V2Migrator { +public interface DestinationV1V2Migrator { /** * This is the primary entrypoint to this interface @@ -17,8 +17,8 @@ public interface DestinationV1V2Migrator { * @param streamConfig the stream to assess migration needs */ void migrateIfNecessary( - final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final StreamConfig streamConfig) throws TableNotMigratedException, UnexpectedSchemaException, Exception; diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/InitialRawTableState.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/InitialRawTableState.java new file mode 100644 index 000000000000..a037daebfa40 --- /dev/null +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/InitialRawTableState.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.base.destination.typing_deduping; + +import java.time.Instant; +import java.util.Optional; + +public record InitialRawTableState(boolean hasUnprocessedRecords, Optional maxProcessedTimestamp) { + +} diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpDestinationV1V2Migrator.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpDestinationV1V2Migrator.java index d9e49257d0a7..f7f5b275768f 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpDestinationV1V2Migrator.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpDestinationV1V2Migrator.java @@ -4,11 +4,11 @@ package io.airbyte.integrations.base.destination.typing_deduping; -public class NoOpDestinationV1V2Migrator implements DestinationV1V2Migrator { +public class NoOpDestinationV1V2Migrator implements DestinationV1V2Migrator { @Override - public void migrateIfNecessary(final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + public void migrateIfNecessary(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final StreamConfig streamConfig) throws TableNotMigratedException, UnexpectedSchemaException { // Do nothing diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java index 1fb3faf59def..f76bd2e07019 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/NoOpTyperDeduperWithV1V2Migrations.java @@ -30,19 +30,19 @@ * json->string migrations in the raw tables. */ @Slf4j -public class NoOpTyperDeduperWithV1V2Migrations implements TyperDeduper { +public class NoOpTyperDeduperWithV1V2Migrations implements TyperDeduper { - private final DestinationV1V2Migrator v1V2Migrator; + private final DestinationV1V2Migrator v1V2Migrator; private final V2TableMigrator v2TableMigrator; private final ExecutorService executorService; private final ParsedCatalog parsedCatalog; - private final SqlGenerator sqlGenerator; - private final DestinationHandler destinationHandler; + private final SqlGenerator sqlGenerator; + private final DestinationHandler destinationHandler; - public NoOpTyperDeduperWithV1V2Migrations(final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, + public NoOpTyperDeduperWithV1V2Migrations(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, final ParsedCatalog parsedCatalog, - final DestinationV1V2Migrator v1V2Migrator, + final DestinationV1V2Migrator v1V2Migrator, final V2TableMigrator v2TableMigrator) { this.sqlGenerator = sqlGenerator; this.destinationHandler = destinationHandler; diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/SqlGenerator.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/SqlGenerator.java index 568fd688e9bb..bb12237ebbf9 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/SqlGenerator.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/SqlGenerator.java @@ -9,7 +9,7 @@ import java.time.Instant; import java.util.Optional; -public interface SqlGenerator { +public interface SqlGenerator { StreamId buildStreamId(String namespace, String name, String rawNamespaceOverride); @@ -23,9 +23,7 @@ default ColumnId buildColumnId(final String name) { * Generate a SQL statement to create a fresh table to match the given stream. *

* The generated SQL should throw an exception if the table already exists and {@code force} is - * false. Callers should use - * {@link #existingSchemaMatchesStreamConfig(StreamConfig, java.lang.Object)} if the table is known - * to exist, and potentially softReset + * false. * * @param suffix A suffix to add to the stream name. Useful for full refresh overwrite syncs, where * we write the entire sync to a temp table. @@ -43,15 +41,6 @@ default ColumnId buildColumnId(final String name) { */ Sql createSchema(final String schema); - /** - * Check the final table's schema and compare it to what the stream config would generate. - * - * @param stream the stream/stable in question - * @param existingTable the existing table mapped to the stream - * @return whether the existing table matches the expected schema - */ - boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final DialectTableDefinition existingTable); - /** * Generate a SQL statement to copy new data from the raw table into the final table. *

@@ -95,8 +84,8 @@ default ColumnId buildColumnId(final String name) { * reset. * * @param streamId the stream to migrate - * @param namespace - * @param tableName + * @param namespace the namespace of the v1 raw table + * @param tableName name of the v2 raw table * @return a string containing the necessary sql to migrate */ Sql migrateFromV1toV2(StreamId streamId, String namespace, String tableName); diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TypeAndDedupeTransaction.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TypeAndDedupeTransaction.java index a1c1f8cc1684..f350c83e76ca 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TypeAndDedupeTransaction.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/main/java/io/airbyte/integrations/base/destination/typing_deduping/TypeAndDedupeTransaction.java @@ -26,11 +26,11 @@ public class TypeAndDedupeTransaction { * @param suffix table suffix for temporary tables * @throws Exception if the safe query fails */ - public static void executeTypeAndDedupe(final SqlGenerator sqlGenerator, - final DestinationHandler destinationHandler, - final StreamConfig streamConfig, - final Optional minExtractedAt, - final String suffix) + public static void executeTypeAndDedupe(final SqlGenerator sqlGenerator, + final DestinationHandler destinationHandler, + final StreamConfig streamConfig, + final Optional minExtractedAt, + final String suffix) throws Exception { try { LOGGER.info("Attempting typing and deduping for {}.{} with suffix {}", streamConfig.id().originalNamespace(), streamConfig.id().originalName(), @@ -62,7 +62,9 @@ public static void executeTypeAndDedupe(final SqlGenerator prepareAllSchemas(parsedCatalog: ParsedCatalog, sqlGenerator: SqlGenerator, destinationHandler: DestinationHandler) { +fun prepareAllSchemas(parsedCatalog: ParsedCatalog, sqlGenerator: SqlGenerator, destinationHandler: DestinationHandler) { val rawSchema = parsedCatalog.streams.mapNotNull { it.id.rawNamespace } val finalSchema = parsedCatalog.streams.mapNotNull { it.id.finalNamespace } val createAllSchemasSql = rawSchema.union(finalSchema) diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParserTest.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParserTest.java index 3922f8ebe4bf..b0237657058b 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParserTest.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/CatalogParserTest.java @@ -19,7 +19,7 @@ class CatalogParserTest { - private SqlGenerator sqlGenerator; + private SqlGenerator sqlGenerator; private CatalogParser parser; @BeforeEach diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduperTest.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduperTest.java index c81629611501..916c0235722d 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduperTest.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DefaultTyperDeduperTest.java @@ -7,6 +7,7 @@ import static io.airbyte.integrations.base.destination.typing_deduping.Sql.separately; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.ignoreStubs; @@ -31,42 +32,58 @@ public class DefaultTyperDeduperTest { private MockSqlGenerator sqlGenerator; - private DestinationHandler destinationHandler; + private DestinationHandler destinationHandler; - private DestinationV1V2Migrator migrator; + private List initialStates; + + private DestinationV1V2Migrator migrator; private TyperDeduper typerDeduper; @BeforeEach void setup() throws Exception { sqlGenerator = spy(new MockSqlGenerator()); destinationHandler = mock(DestinationHandler.class); - when(destinationHandler.getInitialRawTableState(any())).thenReturn(new DestinationHandler.InitialRawTableState(true, Optional.empty())); - migrator = new NoOpDestinationV1V2Migrator<>(); + DestinationInitialState overwriteNsState = mock(DestinationInitialState.class); + DestinationInitialState appendNsState = mock(DestinationInitialState.class); + DestinationInitialState dedupeNsState = mock(DestinationInitialState.class); + StreamConfig overwriteStreamConfig = new StreamConfig( + new StreamId("overwrite_ns", "overwrite_stream", null, null, "overwrite_ns", "overwrite_stream"), + null, + DestinationSyncMode.OVERWRITE, + null, + null, + null); + StreamConfig appendStreamConfig = new StreamConfig( + new StreamId("append_ns", "append_stream", null, null, "append_ns", "append_stream"), + null, + DestinationSyncMode.APPEND, + null, + null, + null); + StreamConfig dedupeStreamConfig = new StreamConfig( + new StreamId("dedup_ns", "dedup_stream", null, null, "dedup_ns", "dedup_stream"), + null, + DestinationSyncMode.APPEND_DEDUP, + null, + null, + null); + when(overwriteNsState.streamConfig()).thenReturn(overwriteStreamConfig); + when(appendNsState.streamConfig()).thenReturn(appendStreamConfig); + when(dedupeNsState.streamConfig()).thenReturn(dedupeStreamConfig); + + initialStates = List.of(overwriteNsState, appendNsState, dedupeNsState); + when(destinationHandler.gatherInitialState(anyList())) + .thenReturn(initialStates); + initialStates.forEach(initialState -> when(initialState.initialRawTableState()).thenReturn(new InitialRawTableState(true, Optional.empty()))); + + migrator = new NoOpDestinationV1V2Migrator(); final ParsedCatalog parsedCatalog = new ParsedCatalog(List.of( - new StreamConfig( - new StreamId("overwrite_ns", "overwrite_stream", null, null, "overwrite_ns", "overwrite_stream"), - null, - DestinationSyncMode.OVERWRITE, - null, - null, - null), - new StreamConfig( - new StreamId("append_ns", "append_stream", null, null, "append_ns", "append_stream"), - null, - DestinationSyncMode.APPEND, - null, - null, - null), - new StreamConfig( - new StreamId("dedup_ns", "dedup_stream", null, null, "dedup_ns", "dedup_stream"), - null, - DestinationSyncMode.APPEND_DEDUP, - null, - null, - null))); - - typerDeduper = new DefaultTyperDeduper<>(sqlGenerator, destinationHandler, parsedCatalog, migrator, 1); + overwriteStreamConfig, + appendStreamConfig, + dedupeStreamConfig)); + + typerDeduper = new DefaultTyperDeduper(sqlGenerator, destinationHandler, parsedCatalog, migrator); } /** @@ -74,7 +91,8 @@ void setup() throws Exception { */ @Test void emptyDestination() throws Exception { - when(destinationHandler.findExistingTable(any())).thenReturn(Optional.empty()); + initialStates.forEach(initialState -> when(initialState.isFinalTablePresent()).thenReturn(false)); + // when(destinationHandler.findExistingTable(any())).thenReturn(Optional.empty()); typerDeduper.prepareTables(); verify(destinationHandler).execute(separately("CREATE SCHEMA overwrite_ns", "CREATE SCHEMA append_ns", "CREATE SCHEMA dedup_ns")); @@ -103,9 +121,11 @@ void emptyDestination() throws Exception { */ @Test void existingEmptyTable() throws Exception { - when(destinationHandler.findExistingTable(any())).thenReturn(Optional.of("foo")); - when(destinationHandler.isFinalTableEmpty(any())).thenReturn(true); - when(sqlGenerator.existingSchemaMatchesStreamConfig(any(), any())).thenReturn(false); + initialStates.forEach(initialState -> { + when(initialState.isFinalTablePresent()).thenReturn(true); + when(initialState.isFinalTableEmpty()).thenReturn(true); + when(initialState.isSchemaMismatch()).thenReturn(true); + }); typerDeduper.prepareTables(); verify(destinationHandler).execute(separately("CREATE SCHEMA overwrite_ns", "CREATE SCHEMA append_ns", "CREATE SCHEMA dedup_ns")); verify(destinationHandler).execute(Sql.of("CREATE TABLE overwrite_ns.overwrite_stream_airbyte_tmp")); @@ -138,9 +158,11 @@ void existingEmptyTable() throws Exception { */ @Test void existingEmptyTableMatchingSchema() throws Exception { - when(destinationHandler.findExistingTable(any())).thenReturn(Optional.of("foo")); - when(destinationHandler.isFinalTableEmpty(any())).thenReturn(true); - when(sqlGenerator.existingSchemaMatchesStreamConfig(any(), any())).thenReturn(true); + initialStates.forEach(initialState -> { + when(initialState.isFinalTablePresent()).thenReturn(true); + when(initialState.isFinalTableEmpty()).thenReturn(true); + when(initialState.isSchemaMismatch()).thenReturn(true); + }); typerDeduper.prepareTables(); verify(destinationHandler).execute(separately("CREATE SCHEMA overwrite_ns", "CREATE SCHEMA append_ns", "CREATE SCHEMA dedup_ns")); @@ -154,10 +176,12 @@ void existingEmptyTableMatchingSchema() throws Exception { */ @Test void existingNonemptyTable() throws Exception { - when(destinationHandler.getInitialRawTableState(any())) - .thenReturn(new DestinationHandler.InitialRawTableState(true, Optional.of(Instant.parse("2023-01-01T12:34:56Z")))); - when(destinationHandler.findExistingTable(any())).thenReturn(Optional.of("foo")); - when(destinationHandler.isFinalTableEmpty(any())).thenReturn(false); + initialStates.forEach(initialState -> { + when(initialState.isFinalTablePresent()).thenReturn(true); + when(initialState.isFinalTableEmpty()).thenReturn(false); + when(initialState.isSchemaMismatch()).thenReturn(true); + when(initialState.initialRawTableState()).thenReturn(new InitialRawTableState(true, Optional.of(Instant.parse("2023-01-01T12:34:56Z")))); + }); typerDeduper.prepareTables(); verify(destinationHandler).execute(separately("CREATE SCHEMA overwrite_ns", "CREATE SCHEMA append_ns", "CREATE SCHEMA dedup_ns")); @@ -197,10 +221,12 @@ void existingNonemptyTable() throws Exception { */ @Test void existingNonemptyTableMatchingSchema() throws Exception { - when(destinationHandler.getInitialRawTableState(any())).thenReturn(new DestinationHandler.InitialRawTableState(true, Optional.of(Instant.now()))); - when(destinationHandler.findExistingTable(any())).thenReturn(Optional.of("foo")); - when(destinationHandler.isFinalTableEmpty(any())).thenReturn(false); - when(sqlGenerator.existingSchemaMatchesStreamConfig(any(), any())).thenReturn(true); + initialStates.forEach(initialState -> { + when(initialState.isFinalTablePresent()).thenReturn(true); + when(initialState.isFinalTableEmpty()).thenReturn(false); + when(initialState.isSchemaMismatch()).thenReturn(false); + when(initialState.initialRawTableState()).thenReturn(new InitialRawTableState(true, Optional.of(Instant.now()))); + }); typerDeduper.prepareTables(); // NB: We only create one tmp table here. @@ -236,7 +262,7 @@ void failedSetup() throws Exception { */ @Test void noUnprocessedRecords() throws Exception { - when(destinationHandler.getInitialRawTableState(any())).thenReturn(new DestinationHandler.InitialRawTableState(false, Optional.empty())); + initialStates.forEach(initialState -> when(initialState.initialRawTableState()).thenReturn(new InitialRawTableState(false, Optional.empty()))); typerDeduper.prepareTables(); clearInvocations(destinationHandler); @@ -258,8 +284,8 @@ void noUnprocessedRecords() throws Exception { */ @Test void unprocessedRecords() throws Exception { - when(destinationHandler.getInitialRawTableState(any())) - .thenReturn(new DestinationHandler.InitialRawTableState(true, Optional.of(Instant.parse("2023-01-23T12:34:56Z")))); + initialStates.forEach(initialState -> when(initialState.initialRawTableState()) + .thenReturn(new InitialRawTableState(true, Optional.of(Instant.parse("2023-01-23T12:34:56Z"))))); typerDeduper.prepareTables(); clearInvocations(destinationHandler); diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2MigratorTest.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2MigratorTest.java index 86893c442ef9..0e4c80321055 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2MigratorTest.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/DestinationV1V2MigratorTest.java @@ -74,7 +74,7 @@ public void testMismatchedSchemaThrowsException() throws Exception { public void testMigrate() throws Exception { final var sqlGenerator = new MockSqlGenerator(); final StreamConfig stream = new StreamConfig(STREAM_ID, null, DestinationSyncMode.APPEND_DEDUP, null, null, null); - final DestinationHandler handler = Mockito.mock(DestinationHandler.class); + final DestinationHandler handler = Mockito.mock(DestinationHandler.class); final var sql = sqlGenerator.migrateFromV1toV2(STREAM_ID, "v1_raw_namespace", "v1_raw_table"); // All is well final var migrator = noIssuesMigrator(); diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/MockSqlGenerator.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/MockSqlGenerator.java index c9fed75526a1..3ef59aa91e21 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/MockSqlGenerator.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/test/java/io/airbyte/integrations/base/destination/typing_deduping/MockSqlGenerator.java @@ -10,7 +10,7 @@ /** * Basic SqlGenerator mock. See {@link DefaultTyperDeduperTest} for example usage. */ -class MockSqlGenerator implements SqlGenerator { +class MockSqlGenerator implements SqlGenerator { @Override public StreamId buildStreamId(final String namespace, final String name, final String rawNamespaceOverride) { @@ -32,11 +32,6 @@ public Sql createTable(final StreamConfig stream, final String suffix, final boo return Sql.of("CREATE TABLE " + stream.id().finalTableId("", suffix)); } - @Override - public boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final String existingTable) throws TableNotMigratedException { - return false; - } - @Override public Sql updateTable(final StreamConfig stream, final String finalSuffix, diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseSqlGeneratorIntegrationTest.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseSqlGeneratorIntegrationTest.java index cfc7eae3fa8a..93e62670a99d 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseSqlGeneratorIntegrationTest.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseSqlGeneratorIntegrationTest.java @@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.Streams; @@ -51,7 +50,7 @@ * {@link #getDestinationHandler()} in a {@link org.junit.jupiter.api.BeforeEach} method. */ @Execution(ExecutionMode.CONCURRENT) -public abstract class BaseSqlGeneratorIntegrationTest { +public abstract class BaseSqlGeneratorIntegrationTest { private static final Logger LOGGER = LoggerFactory.getLogger(BaseSqlGeneratorIntegrationTest.class); /** @@ -104,8 +103,8 @@ public abstract class BaseSqlGeneratorIntegrationTest { */ protected StreamConfig cdcIncrementalAppendStream; - protected SqlGenerator generator; - protected DestinationHandler destinationHandler; + protected SqlGenerator generator; + protected DestinationHandler destinationHandler; protected String namespace; protected StreamId streamId; @@ -113,9 +112,9 @@ public abstract class BaseSqlGeneratorIntegrationTest { private ColumnId cursor; private LinkedHashMap COLUMNS; - protected abstract SqlGenerator getSqlGenerator(); + protected abstract SqlGenerator getSqlGenerator(); - protected abstract DestinationHandler getDestinationHandler(); + protected abstract DestinationHandler getDestinationHandler(); /** * Subclasses should override this method if they need to make changes to the stream ID. For @@ -273,6 +272,14 @@ public void teardown() throws Exception { teardownNamespace(namespace); } + private DestinationInitialState getDestinationInitialState(StreamConfig streamConfig) throws Exception { + final List initialState = + destinationHandler.gatherInitialState(List.of(streamConfig)); + assertEquals(1, initialState.size(), "gatherInitialState returned the wrong number of futures"); + assertTrue(initialState.getFirst().isFinalTablePresent(), "Destination handler could not find existing table"); + return initialState.getFirst(); + } + /** * Create a table and verify that we correctly recognize it as identical to itself. */ @@ -280,14 +287,9 @@ public void teardown() throws Exception { public void detectNoSchemaChange() throws Exception { final Sql createTable = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(createTable); - - final Optional existingTable = destinationHandler.findExistingTable(streamId); - if (!existingTable.isPresent()) { - fail("Destination handler could not find existing table"); - } - - assertTrue( - generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTable.get()), + final DestinationInitialState destinationInitialState = getDestinationInitialState(incrementalDedupStream); + assertFalse( + destinationInitialState.isSchemaMismatch(), "Unchanged schema was incorrectly detected as a schema change."); } @@ -298,18 +300,12 @@ public void detectNoSchemaChange() throws Exception { public void detectColumnAdded() throws Exception { final Sql createTable = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(createTable); - - final Optional existingTable = destinationHandler.findExistingTable(streamId); - if (!existingTable.isPresent()) { - fail("Destination handler could not find existing table"); - } - incrementalDedupStream.columns().put( generator.buildColumnId("new_column"), AirbyteProtocolType.STRING); - - assertFalse( - generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTable.get()), + final DestinationInitialState destinationInitialState = getDestinationInitialState(incrementalDedupStream); + assertTrue( + destinationInitialState.isSchemaMismatch(), "Adding a new column was not detected as a schema change."); } @@ -320,16 +316,10 @@ public void detectColumnAdded() throws Exception { public void detectColumnRemoved() throws Exception { final Sql createTable = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(createTable); - - final Optional existingTable = destinationHandler.findExistingTable(streamId); - if (!existingTable.isPresent()) { - fail("Destination handler could not find existing table"); - } - incrementalDedupStream.columns().remove(generator.buildColumnId("string")); - - assertFalse( - generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTable.get()), + final DestinationInitialState destinationInitialState = getDestinationInitialState(incrementalDedupStream); + assertTrue( + destinationInitialState.isSchemaMismatch(), "Removing a column was not detected as a schema change."); } @@ -340,18 +330,12 @@ public void detectColumnRemoved() throws Exception { public void detectColumnChanged() throws Exception { final Sql createTable = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(createTable); - - final Optional existingTable = destinationHandler.findExistingTable(streamId); - if (!existingTable.isPresent()) { - fail("Destination handler could not find existing table"); - } - incrementalDedupStream.columns().put( generator.buildColumnId("string"), AirbyteProtocolType.INTEGER); - - assertFalse( - generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTable.get()), + final DestinationInitialState destinationInitialState = getDestinationInitialState(incrementalDedupStream); + assertTrue( + destinationInitialState.isSchemaMismatch(), "Altering a column was not detected as a schema change."); } @@ -389,6 +373,11 @@ public void incrementalDedupSameNameNamespace() throws Exception { verifyRecordCounts(1, rawRecords, 1, finalRecords); } + private DestinationInitialState getOnly(final List initialStates) { + assertEquals(1, initialStates.size()); + return initialStates.getFirst(); + } + /** * Run a full T+D update for an incremental-dedup stream, writing to a final table with "_foo" * suffix, with values for all data types. Verifies all behaviors for all types: @@ -414,7 +403,8 @@ public void allTypes() throws Exception { streamId, BaseTypingDedupingTest.readRecords("sqlgenerator/alltypes_inputrecords.jsonl")); - assertTrue(destinationHandler.isFinalTableEmpty(streamId), "Final table should be empty before T+D"); + DestinationInitialState initialState = getOnly(destinationHandler.gatherInitialState(List.of(incrementalDedupStream))); + assertTrue(initialState.isFinalTableEmpty(), "Final table should be empty before T+D"); TypeAndDedupeTransaction.executeTypeAndDedupe(generator, destinationHandler, incrementalDedupStream, Optional.empty(), ""); @@ -423,7 +413,8 @@ public void allTypes() throws Exception { dumpRawTableRecords(streamId), "sqlgenerator/alltypes_expectedrecords_final.jsonl", dumpFinalTableRecords(streamId, "")); - assertFalse(destinationHandler.isFinalTableEmpty(streamId), "Final table should not be empty after T+D"); + initialState = getOnly(destinationHandler.gatherInitialState(List.of(incrementalDedupStream))); + assertFalse(initialState.isFinalTableEmpty(), "Final table should not be empty after T+D"); } /** @@ -437,13 +428,22 @@ public void allTypesUnsafe() throws Exception { streamId, BaseTypingDedupingTest.readRecords("sqlgenerator/alltypes_unsafe_inputrecords.jsonl")); - assertTrue(destinationHandler.isFinalTableEmpty(streamId), "Final table should be empty before T+D"); + DestinationInitialState initialState = getOnly(destinationHandler.gatherInitialState(List.of(incrementalDedupStream))); + assertTrue(initialState.isFinalTableEmpty(), "Final table should be empty before T+D"); // Instead of using the full T+D transaction, explicitly run with useSafeCasting=false. final Sql unsafeSql = generator.updateTable(incrementalDedupStream, "", Optional.empty(), false); destinationHandler.execute(unsafeSql); - assertFalse(destinationHandler.isFinalTableEmpty(streamId), "Final table should not be empty after T+D"); + initialState = getOnly(destinationHandler.gatherInitialState(List.of(incrementalDedupStream))); + assertFalse(initialState.isFinalTableEmpty(), "Final table should not be empty after T+D"); + } + + private InitialRawTableState getInitialRawTableState(StreamConfig streamConfig) throws Exception { + List initialStates = + destinationHandler.gatherInitialState(List.of(streamConfig)); + assertEquals(1, initialStates.size()); + return initialStates.getFirst().initialRawTableState(); } /** @@ -453,11 +453,11 @@ public void allTypesUnsafe() throws Exception { @Test public void minTimestampBehavesCorrectly() throws Exception { // When the raw table doesn't exist, there are no unprocessed records and no timestamp - assertEquals(new DestinationHandler.InitialRawTableState(false, Optional.empty()), destinationHandler.getInitialRawTableState(streamId)); + assertEquals(new InitialRawTableState(false, Optional.empty()), getInitialRawTableState(incrementalAppendStream)); // When the raw table is empty, there are still no unprocessed records and no timestamp createRawTable(streamId); - assertEquals(new DestinationHandler.InitialRawTableState(false, Optional.empty()), destinationHandler.getInitialRawTableState(streamId)); + assertEquals(new InitialRawTableState(false, Optional.empty()), getInitialRawTableState(incrementalAppendStream)); // If we insert some raw records with null loaded_at, we should get the min extracted_at insertRawTableRecords( @@ -479,7 +479,7 @@ public void minTimestampBehavesCorrectly() throws Exception { "_airbyte_data": {} } """))); - DestinationHandler.InitialRawTableState tableState = destinationHandler.getInitialRawTableState(streamId); + InitialRawTableState tableState = getInitialRawTableState(incrementalAppendStream); assertTrue(tableState.hasUnprocessedRecords(), "When all raw records have null loaded_at, we should recognize that there are unprocessed records"); assertTrue( @@ -492,8 +492,8 @@ public void minTimestampBehavesCorrectly() throws Exception { TypeAndDedupeTransaction.executeTypeAndDedupe(generator, destinationHandler, incrementalAppendStream, Optional.empty(), ""); assertEquals( - destinationHandler.getInitialRawTableState(streamId), - new DestinationHandler.InitialRawTableState(false, Optional.of(Instant.parse("2023-01-02T00:00:00Z"))), + getInitialRawTableState(incrementalAppendStream), + new InitialRawTableState(false, Optional.of(Instant.parse("2023-01-02T00:00:00Z"))), "When all raw records have non-null loaded_at, we should recognize that there are no unprocessed records, and the min timestamp should be equal to the latest extracted_at"); // If we insert another raw record with older extracted_at than the typed records, we should fetch a @@ -511,7 +511,7 @@ public void minTimestampBehavesCorrectly() throws Exception { "_airbyte_data": {} } """))); - tableState = destinationHandler.getInitialRawTableState(streamId); + tableState = getInitialRawTableState(incrementalAppendStream); // this is a pretty confusing pair of assertions. To explain them in more detail: There are three // records in the raw table: // * loaded_at not null, extracted_at = 2023-01-01 00:00Z @@ -549,7 +549,7 @@ public void handlePreexistingRecords() throws Exception { streamId, BaseTypingDedupingTest.readRecords("sqlgenerator/alltypes_inputrecords.jsonl")); - final DestinationHandler.InitialRawTableState tableState = destinationHandler.getInitialRawTableState(streamId); + final InitialRawTableState tableState = getInitialRawTableState(incrementalDedupStream); assertAll( () -> assertTrue(tableState.hasUnprocessedRecords(), "After writing some raw records, we should recognize that there are unprocessed records"), @@ -575,7 +575,7 @@ public void handleNoPreexistingRecords() throws Exception { generator.buildColumnId("IamACaseSensitiveColumnName"), AirbyteProtocolType.STRING); createRawTable(streamId); - final DestinationHandler.InitialRawTableState tableState = destinationHandler.getInitialRawTableState(streamId); + final InitialRawTableState tableState = getInitialRawTableState(incrementalDedupStream); assertAll( () -> assertFalse(tableState.hasUnprocessedRecords(), "With an empty raw table, we should recognize that there are no unprocessed records"), () -> assertEquals(Optional.empty(), tableState.maxProcessedTimestamp(), "With an empty raw table, the min timestamp should be empty")); @@ -900,7 +900,7 @@ public void testCdcOrdering_updateAfterDelete() throws Exception { streamId, BaseTypingDedupingTest.readRecords("sqlgenerator/cdcordering_updateafterdelete_inputrecords.jsonl")); - final DestinationHandler.InitialRawTableState tableState = destinationHandler.getInitialRawTableState(cdcIncrementalDedupStream.id()); + final InitialRawTableState tableState = getInitialRawTableState(cdcIncrementalDedupStream); TypeAndDedupeTransaction.executeTypeAndDedupe(generator, destinationHandler, cdcIncrementalDedupStream, tableState.maxProcessedTimestamp(), ""); verifyRecordCounts( @@ -937,7 +937,7 @@ public void testCdcOrdering_insertAfterDelete() throws Exception { "", BaseTypingDedupingTest.readRecords("sqlgenerator/cdcordering_insertafterdelete_inputrecords_final.jsonl")); - final DestinationHandler.InitialRawTableState tableState = destinationHandler.getInitialRawTableState(cdcIncrementalAppendStream.id()); + final InitialRawTableState tableState = getInitialRawTableState(cdcIncrementalAppendStream); TypeAndDedupeTransaction.executeTypeAndDedupe(generator, destinationHandler, cdcIncrementalDedupStream, tableState.maxProcessedTimestamp(), ""); verifyRecordCounts( 2, @@ -1241,8 +1241,8 @@ public void testCreateTableForce() throws Exception { assertThrows(Exception.class, () -> destinationHandler.execute(createTableNoForce)); // This should not throw an exception destinationHandler.execute(createTableForce); - - assertTrue(destinationHandler.findExistingTable(streamId).isPresent()); + // This method call ensures assertion than finalTable exists + getDestinationInitialState(incrementalDedupStream); } protected void createFinalTable(final StreamConfig stream, final String suffix) throws Exception { diff --git a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseTypingDedupingTest.java b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseTypingDedupingTest.java index 5c7cd00e8ae2..e52c669dc798 100644 --- a/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseTypingDedupingTest.java +++ b/airbyte-cdk/java/airbyte-cdk/typing-deduping/src/testFixtures/java/io/airbyte/integrations/base/destination/typing_deduping/BaseTypingDedupingTest.java @@ -156,7 +156,7 @@ protected boolean checkTableExists(final String streamNamespace, final String st */ protected abstract void teardownStreamAndNamespace(String streamNamespace, String streamName) throws Exception; - protected abstract SqlGenerator getSqlGenerator(); + protected abstract SqlGenerator getSqlGenerator(); /** * Destinations which need to clean up resources after an entire test finishes should override this @@ -215,7 +215,7 @@ public void setup() throws Exception { streamName = "test_stream" + getUniqueSuffix(); streamsToTearDown = new ArrayList<>(); - final SqlGenerator generator = getSqlGenerator(); + final SqlGenerator generator = getSqlGenerator(); DIFFER = new RecordDiffer( getRawMetadataColumnNames(), getFinalMetadataColumnNames(), From 11ea12199e697e95e639ee5740811a4ef6f9dd97 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 17:13:46 -0800 Subject: [PATCH 40/74] .github: fix python_cdk_tests.yml (#35567) --- .github/workflows/python_cdk_tests.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/python_cdk_tests.yml b/.github/workflows/python_cdk_tests.yml index 0873bf4d93ac..0fc8a9b5bacb 100644 --- a/.github/workflows/python_cdk_tests.yml +++ b/.github/workflows/python_cdk_tests.yml @@ -5,10 +5,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - S3_BUILD_CACHE_SECRET_KEY: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - on: workflow_dispatch: push: @@ -36,6 +32,7 @@ jobs: filters: | python_cdk: - 'airbyte-cdk/python/**/*' + run-python-cdk-check: needs: - changes @@ -54,18 +51,8 @@ jobs: run: curl -fsSL https://bootstrap.pypa.io/get-pip.py | python3 - name: Install Pyenv run: python3 -m pip install virtualenv --user - - name: cd airbyte-cdk/python - run: cd airbyte-cdk/python - name: Run Gradle Check on Python CDK - uses: burrunan/gradle-cache-action@v1 - env: - CI: true - with: - job-id: python-cdk-check - read-only: ${{ github.ref != 'refs/heads/master' }} - gradle-distribution-sha-256-sum-warning: false - concurrent: true - arguments: --scan build + run: (cd airbyte-cdk/python && CI=true ./gradlew --no-daemon --no-build-cache --scan check) set-instatus-incident-on-failure: name: Create Instatus Incident on Failure From a36ea608314ac6abb0b136c348edc33561087e56 Mon Sep 17 00:00:00 2001 From: pmossman Date: Fri, 23 Feb 2024 01:53:52 +0000 Subject: [PATCH 41/74] Bump Airbyte version from 0.50.51 to 0.50.52 --- .bumpversion.cfg | 2 +- gradle.properties | 2 +- run-ab-platform.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index edace9078bfd..d2eea00484cb 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.50.51 +current_version = 0.50.52 commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-[a-z]+)? diff --git a/gradle.properties b/gradle.properties index 948e1c94d8d6..c8acd92dea64 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION=0.50.51 +VERSION=0.50.52 # NOTE: some of these values are overwritten in CI! # NOTE: if you want to override this for your local machine, set overrides in ~/.gradle/gradle.properties diff --git a/run-ab-platform.sh b/run-ab-platform.sh index ec4b23527199..b3f9e270dea5 100755 --- a/run-ab-platform.sh +++ b/run-ab-platform.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION=0.50.51 +VERSION=0.50.52 # Run away from anything even a little scary set -o nounset # -u exit if a variable is not set set -o errexit # -f exit for any command failure" From 9144011b54cad1b157feebca3d23be620d18cf68 Mon Sep 17 00:00:00 2001 From: Stephane Geneix <147216312+stephane-airbyte@users.noreply.github.com> Date: Thu, 22 Feb 2024 19:37:32 -0800 Subject: [PATCH 42/74] add entry into JAVA_OPTS to always select log4j2.xml as our logger configuration (#35569) --- airbyte-integrations/bases/base-java/javabase.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-integrations/bases/base-java/javabase.sh b/airbyte-integrations/bases/base-java/javabase.sh index d835d4e9e0eb..59ceb87713fa 100755 --- a/airbyte-integrations/bases/base-java/javabase.sh +++ b/airbyte-integrations/bases/base-java/javabase.sh @@ -16,7 +16,7 @@ if [[ $IS_CAPTURE_HEAP_DUMP_ON_ERROR = true ]]; then fi fi #30781 - Allocate 32KB for log4j appender buffer to ensure that each line is logged in a single println -JAVA_OPTS=$JAVA_OPTS" -Dlog4j.encoder.byteBufferSize=32768" +JAVA_OPTS=$JAVA_OPTS" -Dlog4j.encoder.byteBufferSize=32768 -Dlog4j2.configurationFile=log4j2.xml" export JAVA_OPTS # Wrap run script in a script so that we can lazy evaluate the value of APPLICATION. APPLICATION is From f44ea6aaf401e24a8d5d9d31dccea11f462b6868 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 19:58:10 -0800 Subject: [PATCH 43/74] destination-s3: bump patch version following #35569 (#35576) Co-authored-by: Stephane Geneix --- airbyte-integrations/connectors/destination-s3/metadata.yaml | 2 +- docs/integrations/destinations/s3.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/destination-s3/metadata.yaml b/airbyte-integrations/connectors/destination-s3/metadata.yaml index aec7c1e0e295..617cf229c6bb 100644 --- a/airbyte-integrations/connectors/destination-s3/metadata.yaml +++ b/airbyte-integrations/connectors/destination-s3/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: file connectorType: destination definitionId: 4816b78f-1489-44c1-9060-4b19d5fa9362 - dockerImageTag: 0.5.8 + dockerImageTag: 0.5.9 dockerRepository: airbyte/destination-s3 githubIssueLabel: destination-s3 icon: s3.svg diff --git a/docs/integrations/destinations/s3.md b/docs/integrations/destinations/s3.md index dca7fc450427..d29d32464c4f 100644 --- a/docs/integrations/destinations/s3.md +++ b/docs/integrations/destinations/s3.md @@ -402,6 +402,7 @@ In order for everything to work correctly, it is also necessary that the user wh | Version | Date | Pull Request | Subject | | :------ | :--------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0.5.9 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 0.5.8 | 2024-01-03 | [#33924](https://github.com/airbytehq/airbyte/pull/33924) | Add new ap-southeast-3 AWS region | | 0.5.7 | 2023-12-28 | [#33788](https://github.com/airbytehq/airbyte/pull/33788) | Thread-safe fix for file part names | | 0.5.6 | 2023-12-08 | [#33263](https://github.com/airbytehq/airbyte/pull/33263) | (incorrect filename format, do not use) Adopt java CDK version 0.7.0. | From e10bbbf890ee79f5628e8eae565dfa69316b6732 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 20:05:13 -0800 Subject: [PATCH 44/74] destination-snowflake: bump patch version following #35569 (#35575) Co-authored-by: Stephane Geneix --- .../connectors/destination-snowflake/metadata.yaml | 2 +- docs/integrations/destinations/snowflake.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/destination-snowflake/metadata.yaml b/airbyte-integrations/connectors/destination-snowflake/metadata.yaml index 2f49fddbe294..021cfd26e685 100644 --- a/airbyte-integrations/connectors/destination-snowflake/metadata.yaml +++ b/airbyte-integrations/connectors/destination-snowflake/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 424892c4-daac-4491-b35d-c6688ba547ba - dockerImageTag: 3.5.12 + dockerImageTag: 3.5.13 dockerRepository: airbyte/destination-snowflake documentationUrl: https://docs.airbyte.com/integrations/destinations/snowflake githubIssueLabel: destination-snowflake diff --git a/docs/integrations/destinations/snowflake.md b/docs/integrations/destinations/snowflake.md index 3160d8c39dd9..f7a6f3e7a95d 100644 --- a/docs/integrations/destinations/snowflake.md +++ b/docs/integrations/destinations/snowflake.md @@ -246,6 +246,7 @@ Otherwise, make sure to grant the role the required permissions in the desired n | Version | Date | Pull Request | Subject | |:----------------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.5.13 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 3.5.12 | 2024-02-15 | [35240](https://github.com/airbytehq/airbyte/pull/35240) | Adopt CDK 0.20.9 | | 3.5.11 | 2024-02-12 | [35194](https://github.com/airbytehq/airbyte/pull/35194) | Reorder auth options | | 3.5.10 | 2024-02-12 | [35144](https://github.com/airbytehq/airbyte/pull/35144) | Adopt CDK 0.20.2 | From 084671b5805d361d63d389c2f88c314d5421c1e1 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 20:11:27 -0800 Subject: [PATCH 45/74] destination-bigquery: bump patch version following #35569 (#35574) Co-authored-by: Stephane Geneix --- .../connectors/destination-bigquery/metadata.yaml | 2 +- docs/integrations/destinations/bigquery.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml index 04c3fbdd22a2..e3e73d6a5c98 100644 --- a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml +++ b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 22f6c74f-5699-40ff-833c-4a879ea40133 - dockerImageTag: 2.4.10 + dockerImageTag: 2.4.11 dockerRepository: airbyte/destination-bigquery documentationUrl: https://docs.airbyte.com/integrations/destinations/bigquery githubIssueLabel: destination-bigquery diff --git a/docs/integrations/destinations/bigquery.md b/docs/integrations/destinations/bigquery.md index 1a6a55fa40e0..7f475376d592 100644 --- a/docs/integrations/destinations/bigquery.md +++ b/docs/integrations/destinations/bigquery.md @@ -210,6 +210,7 @@ tutorials: | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.4.11 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 2.4.10 | 2024-02-15 | [35240](https://github.com/airbytehq/airbyte/pull/35240) | Adopt CDK 0.20.9 | | 2.4.9 | 2024-02-15 | [35285](https://github.com/airbytehq/airbyte/pull/35285) | Adopt CDK 0.20.8 | | 2.4.8 | 2024-02-12 | [35144](https://github.com/airbytehq/airbyte/pull/35144) | Adopt CDK 0.20.2 | From 2b370f84c2f6969313b390eaba595d06c4d8b7c1 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 20:19:56 -0800 Subject: [PATCH 46/74] source-mysql: bump patch version following #35569 (#35573) Co-authored-by: Stephane Geneix --- airbyte-integrations/connectors/source-mysql/metadata.yaml | 2 +- docs/integrations/sources/mysql.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-mysql/metadata.yaml b/airbyte-integrations/connectors/source-mysql/metadata.yaml index f336314ed65b..761f7233b935 100644 --- a/airbyte-integrations/connectors/source-mysql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mysql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: 435bb9a5-7887-4809-aa58-28c27df0d7ad - dockerImageTag: 3.3.9 + dockerImageTag: 3.3.10 dockerRepository: airbyte/source-mysql documentationUrl: https://docs.airbyte.com/integrations/sources/mysql githubIssueLabel: source-mysql diff --git a/docs/integrations/sources/mysql.md b/docs/integrations/sources/mysql.md index d6d50b1ab4be..d109a13a2847 100644 --- a/docs/integrations/sources/mysql.md +++ b/docs/integrations/sources/mysql.md @@ -223,6 +223,7 @@ Any database or table encoding combination of charset and collation is supported | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.3.10 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 3.3.9 | 2024-02-21 | [35525](https://github.com/airbytehq/airbyte/pull/35338) | Adopt 0.21.4 and reduce cdc state compression threshold to 1MB. | | 3.3.8 | 2024-02-20 | [35338](https://github.com/airbytehq/airbyte/pull/35338) | Add config to throw an error on invalid CDC position. | | 3.3.7 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | From 407cba86a58cc9775bfe1ece6a6d509632d55cbe Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 20:23:14 -0800 Subject: [PATCH 47/74] source-postgres: bump patch version following #35569 (#35572) Co-authored-by: Stephane Geneix --- airbyte-integrations/connectors/source-postgres/metadata.yaml | 2 +- docs/integrations/sources/postgres.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-postgres/metadata.yaml b/airbyte-integrations/connectors/source-postgres/metadata.yaml index 8f23c3a5a6be..22a65152d31f 100644 --- a/airbyte-integrations/connectors/source-postgres/metadata.yaml +++ b/airbyte-integrations/connectors/source-postgres/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: decd338e-5647-4c0b-adf4-da0e75f5a750 - dockerImageTag: 3.3.11 + dockerImageTag: 3.3.12 dockerRepository: airbyte/source-postgres documentationUrl: https://docs.airbyte.com/integrations/sources/postgres githubIssueLabel: source-postgres diff --git a/docs/integrations/sources/postgres.md b/docs/integrations/sources/postgres.md index d9cdddfc9f7e..56ddc87ab7bb 100644 --- a/docs/integrations/sources/postgres.md +++ b/docs/integrations/sources/postgres.md @@ -292,6 +292,7 @@ According to Postgres [documentation](https://www.postgresql.org/docs/14/datatyp | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.3.12 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 3.3.11 | 2024-02-20 | [35304](https://github.com/airbytehq/airbyte/pull/35304) | Add config to throw an error on invalid CDC position and enable it by default. | | 3.3.10 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | | 3.3.9 | 2024-02-13 | [35224](https://github.com/airbytehq/airbyte/pull/35224) | Adopt CDK 0.20.4 | From aa084a94469d5e949575127b4f7a3e5ba6e34754 Mon Sep 17 00:00:00 2001 From: Marius Posta Date: Thu, 22 Feb 2024 20:30:12 -0800 Subject: [PATCH 48/74] source-mongodb-v2: bump patch version following #35569 (#35571) Co-authored-by: Stephane Geneix --- airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml | 2 +- docs/integrations/sources/mongodb-v2.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml b/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml index 88bbd68ae98f..7cfabf8d314a 100644 --- a/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml +++ b/airbyte-integrations/connectors/source-mongodb-v2/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: source definitionId: b2e713cd-cc36-4c0a-b5bd-b47cb8a0561e - dockerImageTag: 1.2.12 + dockerImageTag: 1.2.13 dockerRepository: airbyte/source-mongodb-v2 documentationUrl: https://docs.airbyte.com/integrations/sources/mongodb-v2 githubIssueLabel: source-mongodb-v2 diff --git a/docs/integrations/sources/mongodb-v2.md b/docs/integrations/sources/mongodb-v2.md index 9894fd8d0568..c51d5b6d64f1 100644 --- a/docs/integrations/sources/mongodb-v2.md +++ b/docs/integrations/sources/mongodb-v2.md @@ -214,6 +214,7 @@ For more information regarding configuration parameters, please see [MongoDb Doc | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:----------------------------------------------------------------------------------------------------------| +| 1.2.13 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 1.2.12 | 2024-02-21 | [35526](https://github.com/airbytehq/airbyte/pull/35526) | Improve error handling. | | 1.2.11 | 2024-02-20 | [35375](https://github.com/airbytehq/airbyte/pull/35375) | Add config to throw an error on invalid CDC position and enable it by default. | | 1.2.10 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | From f3dfcb18176735c7dd2a4b55e56c1a127ed37312 Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 23 Feb 2024 08:33:24 +0100 Subject: [PATCH 49/74] airbyte-ci-test.yml: only run if modified internal poetry packages (#35551) --- .github/workflows/airbyte-ci-tests.yml | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/airbyte-ci-tests.yml b/.github/workflows/airbyte-ci-tests.yml index 6d6ec1aa2f4f..c9f62615deab 100644 --- a/.github/workflows/airbyte-ci-tests.yml +++ b/.github/workflows/airbyte-ci-tests.yml @@ -16,7 +16,32 @@ on: - reopened - synchronize jobs: - run-airbyte-ci-poetry-ci: + changes: + runs-on: ubuntu-latest + outputs: + internal_poetry_packages: ${{ steps.changes.outputs.internal_poetry_packages }} + + steps: + - id: changes + uses: dorny/paths-filter@v2 + with: + # Note: expressions within a filter are OR'ed + filters: | + internal_poetry_packages: + - airbyte-lib/** + - airbyte-ci/connectors/pipelines/** + - airbyte-ci/connectors/base_images/** + - airbyte-ci/connectors/common_utils/** + - airbyte-ci/connectors/connector_ops/** + - airbyte-ci/connectors/connectors_qa/** + - airbyte-ci/connectors/ci_credentials/** + - airbyte-ci/connectors/metadata_service/lib/** + - airbyte-ci/connectors/metadata_service/orchestrator/** + - airbyte-integrations/bases/connector-acceptance-test/** + + run-tests: + needs: changes + if: needs.changes.outputs.internal_poetry_packages == 'true' #name: Internal Poetry packages CI # To rename in a follow up PR name: Run Airbyte CI tests From 77c7921ef0728293dd12b3d7f024261b68c4edf6 Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 23 Feb 2024 08:55:11 +0100 Subject: [PATCH 50/74] airbyte-ci-test.yml: checkout repo for path filters when not on PR (#35577) --- .github/workflows/airbyte-ci-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/airbyte-ci-tests.yml b/.github/workflows/airbyte-ci-tests.yml index c9f62615deab..37240d132791 100644 --- a/.github/workflows/airbyte-ci-tests.yml +++ b/.github/workflows/airbyte-ci-tests.yml @@ -22,6 +22,9 @@ jobs: internal_poetry_packages: ${{ steps.changes.outputs.internal_poetry_packages }} steps: + - name: Checkout Airbyte + if: github.event_name != 'pull_request' + uses: actions/checkout@v3 - id: changes uses: dorny/paths-filter@v2 with: From e2742bd11b4557566269d5a80e4e0b26f8c061f2 Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 23 Feb 2024 17:13:55 +0100 Subject: [PATCH 51/74] connectors-ci: early exit when no connector changes (#35578) --- .github/workflows/connectors_tests.yml | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/.github/workflows/connectors_tests.yml b/.github/workflows/connectors_tests.yml index 574208420176..8cd907140cab 100644 --- a/.github/workflows/connectors_tests.yml +++ b/.github/workflows/connectors_tests.yml @@ -22,7 +22,45 @@ on: - opened - synchronize jobs: + changes: + runs-on: ubuntu-latest + outputs: + connectors: ${{ steps.changes.outputs.connectors }} + permissions: + statuses: write + steps: + - name: Checkout Airbyte + if: github.event_name != 'pull_request' + uses: actions/checkout@v3 + - id: changes + uses: dorny/paths-filter@v2 + with: + # Note: expressions within a filter are OR'ed + filters: | + connectors: + - '*' + - 'airbyte-ci/**/*' + - 'airbyte-integrations/connectors/**/*' + - 'airbyte-cdk/**/*' + - 'buildSrc/**/*' + # The Connector CI Tests is a status check emitted by airbyte-ci + # We make it pass once we have determined that there are no changes to the connectors + - name: "Skip Connectors CI tests" + if: steps.changes.outputs.connectors != 'true' && github.event_name == 'pull_request' + run: | + curl --request POST \ + --url https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha }} \ + --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ + --header 'content-type: application/json' \ + --data '{ + "state": "success", + "context": "Connectors CI tests", + "target_url": "${{ github.event.workflow_run.html_url }}" + }' \ + connectors_ci: + needs: changes + if: needs.changes.outputs.connectors == 'true' name: Connectors CI runs-on: connector-test-large timeout-minutes: 1440 # 24 hours From cb25bbef995d8953419e8520e406730ac8a2596d Mon Sep 17 00:00:00 2001 From: Alexandre Cuoci Date: Fri, 23 Feb 2024 11:51:43 -0500 Subject: [PATCH 52/74] Microsoft Entra ID for Self-Managed Enterprise (#35585) --- .../sso-providers/azure-entra-id.md | 64 ++++++++++++++++--- docs/enterprise-setup/implementation-guide.md | 29 ++++++++- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/docs/access-management/sso-providers/azure-entra-id.md b/docs/access-management/sso-providers/azure-entra-id.md index 611aad0b3cb3..3b71e7c2ac7c 100644 --- a/docs/access-management/sso-providers/azure-entra-id.md +++ b/docs/access-management/sso-providers/azure-entra-id.md @@ -1,21 +1,24 @@ --- -sidebar_label: Azure Entra ID -products: cloud-teams +sidebar_label: Microsoft Entra ID +products: cloud-teams, oss-enterprise --- import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; -# Setup Single Sign-On via Azure Entra ID +# Setup Single Sign-On via Microsoft Entra ID -This page guides you through setting up [Single Sign-On](../sso.md) with Airbyte using **Microsoft Azure Entra ID** (formerly known as **Azure Active Directory**). +This page guides you through setting up [Single Sign-On](../sso.md) with Airbyte using **Microsoft Entra ID** (formerly known as **Azure ActiveDirectory**). Airbyte will communicate with your Entra ID using OpenID Connect (OIDC). + + + ## Creating an Entra ID app for Airbyte :::info -The following steps need to be executed by an administrator of your company's Azure Entra ID account. +The following steps need to be executed by an administrator of your company's Microsoft Entra ID account. ::: You'll require to know your **Company Identifier** to create your application. You receive this @@ -25,7 +28,7 @@ from your contact at Airbyte. You will need to create a new Entra ID application for Airbyte. Log into the [Azure Portal](https://portal.azure.com/) and search for the Entra ID service. -On the Overview of Entra ID press **Add** > **App registration** on the top of the screen. +From the overview page of Entra ID, press **Add** > **App registration** on the top of the screen. Specify any name you want (e.g. "Airbyte") and configure a **Redirect URI** of type **Web** with the following value: @@ -39,13 +42,13 @@ Hit **Register** to create the application. To create Client credentials for Airbyte to talk to your application head to **Certificates & Secrets** on the detail screen of your application and select the **Client secrets** tab. -Click **New client secret**, specify any Description you want and any Expire date you want. +Click **New client secret**, specify any Description you want and any expiry date you want. :::tip -We recommend to chose an expiry date of at least 12 months. You'll need to pass the new Client Secret to use every time the old one expires, to continue being able to log in via Entra ID. +We recommend to chose an expiry date of at least 12 months. You'll need to pass in the new client secret every time the old one expires to continue being able to log in via Entra ID. ::: -Copy the **Value** (the Client Secret itself) immediately after creation. You won't be able to view this later on again. +Copy the **Value** (the Client Secret itself) immediately after creation. You won't be able to view this later on. ### Setup information needed @@ -56,3 +59,46 @@ You'll need to pass your Airbyte contact the following information of the create * **OpenID Connect metadata document**: You'll find this in the **Endpoints** panel, that you can open from the top bar on the **Overview** page Once we've received this information from you, We'll setup SSO for you and let you know once it's ready to be used. + + + + +## Creating an Entra ID app for Airbyte + +:::info +The following steps need to be executed by an administrator of your company's Azure Entra ID account. +::: + +### Create application + +You will need to create a new Entra ID application for Airbyte. Log into the [Azure Portal](https://portal.azure.com/) and search for the Entra ID service. + +From the overview page of Entra ID, press **Add** > **App registration** on the top of the screen. The name you select is your app integration name. Once chosen, configure a **Redirect URI** of type **Web** with the following value: + +``` +/auth/realms/airbyte/broker//endpoint +``` + +Hit **Register** to create the application. + +### Create client credentials + +To create client credentials for Airbyte to interface with your application, head to **Certificates & Secrets** on the detail screen of your application and select the **Client secrets** tab. Then: +1. Click **New client secret**, and enter the expiry date of your choosing. You'll need to pass in the new client secret every time the old one expires to continue being able to log in via Entra ID. +2. Copy the **Value** (the client secret itself) immediately after creation. You won't be able to view this later on. + +### Setup information needed + +Once your Microsoft Entra ID app is set up, you're ready to deploy Airbyte Self-Managed Enterprise with SSO. Take note of the following configuration values, as you will need them to configure Airbyte to use your new Okta SSO app integration: + + * OpenID Connect metadata document: You'll find this in the list of endpoints found in the **Endpoints** panel, which you can open from the top bar of the **Overview** page. This will be used to populate the `Domain` field in your `airbyte.yml`. + * App Integration Name: The name of the Entra ID application created in the first step. + * Client ID: You'll find this in the **Essentials** section on the **Overview** page of the application you created. + * Client Secret: The client secret you copied in the previous step. + +Use this information to configure the auth details of your `airbyte.yml` for your Self-Managed Enterprise deployment. To learn more on deploying Self-Managed Enterprise, see our [implementation guide](/enterprise-setup/implementation-guide). + + + + + diff --git a/docs/enterprise-setup/implementation-guide.md b/docs/enterprise-setup/implementation-guide.md index 5a41b8086f48..cde0f05d7349 100644 --- a/docs/enterprise-setup/implementation-guide.md +++ b/docs/enterprise-setup/implementation-guide.md @@ -80,11 +80,14 @@ cp configs/airbyte.sample.yml configs/airbyte.yml 3. Add your Airbyte Self-Managed Enterprise license key to your `airbyte.yml`. -4. Add your [auth details](/enterprise-setup/sso) to your `airbyte.yml`. Auth configurations aren't easy to modify after Airbyte is installed, so please double check them to make sure they're accurate before proceeding. +4. Add your [auth details](/access-management/sso) to your `airbyte.yml`.

Configuring auth in your airbyte.yml file + + + To configure SSO with Okta, add the following at the end of your `airbyte.yml` file: ```yaml @@ -97,8 +100,32 @@ auth: client-secret: $OKTA_CLIENT_SECRET ``` +See the [following guide](/access-management/sso-providers/okta) on how to collect this information for Okta. + + + + +To configure SSO with any identity provider via [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/), such as Azure Entra ID (formerly ActiveDirectory), add the following at the end of your `airbyte.yml` file: + +```yaml +auth: + identity-providers: + - type: oidc + domain: $DOMAIN + app-name: $APP_INTEGRATION_NAME + client-id: $CLIENT_ID + client-secret: $CLIENT_SECRET +``` + +See the [following guide](/access-management/sso-providers/azure-entra-id) on how to collect this information for Azure Entra ID (formerly ActiveDirectory). + + + + To configure basic auth (deploy without SSO), remove the entire `auth:` section from your airbyte.yml config file. You will authenticate with the instance admin user and password included in the your `airbyte.yml`. +To modify auth configurations after Airbyte is installed, you will need to redeploy Airbyte with the additional environment variable `KEYCLOAK_RESET_REALM=TRUE`. As this also resets the list of Airbyte users and permissions, please use this with caution. +
#### Configuring the Airbyte Database From d6346e107688b90b082b2e91861aae50950a883a Mon Sep 17 00:00:00 2001 From: Maxime Carbonneau-Leclerc <3360483+maxi297@users.noreply.github.com> Date: Fri, 23 Feb 2024 12:03:03 -0500 Subject: [PATCH 53/74] Improve documentation on check command (#35542) Co-authored-by: Ella Rohm-Ensing --- docs/understanding-airbyte/airbyte-protocol.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/understanding-airbyte/airbyte-protocol.md b/docs/understanding-airbyte/airbyte-protocol.md index e673ff9f3ade..19f59a160b2f 100644 --- a/docs/understanding-airbyte/airbyte-protocol.md +++ b/docs/understanding-airbyte/airbyte-protocol.md @@ -108,7 +108,12 @@ The `spec` command allows an actor to broadcast information about itself and how check(Config) -> AirbyteConnectionStatus ``` -The `check` command validates that, given a configuration, that the Actor is able to connect and access all resources that it needs in order to operate. e.g. Given some Postgres credentials, it determines whether it can connect to the Postgres database. If it can, it will return a success response. If it fails (perhaps the password is incorrect), it will return a failed response and (when possible) a helpful error message. If an actor's `check` command succeeds, it is expected that all subsequent methods in the sync will also succeed. +The `check` command validates that, given a configuration, that the Actor is able to connect and access all resources that it needs in order to operate. e.g. Given some Postgres credentials, it determines whether it can connect to the Postgres database. The output will be as follows: +- If it can, the `check` command will return a success response. +- If `check` fails because of a configuration issue (perhaps the password is incorrect), it will return a failed response and (when possible) a helpful error message. A failed response will be considered as a config error, i.e. user error. Outputting a trace message detailing the config error is optional, but allows for more detailed debugging of the error. +- If it fails because of a connector issue, the `check` command should output a trace message detailing the failure. It is not expected to receive an `AirbyteConnectionStatus` in this failure case. + +If an actor's `check` command succeeds, it is expected that all subsequent methods in the sync will also succeed. #### Input: From e671aa320dae5fc4f0626cfcf2638904dddf2f08 Mon Sep 17 00:00:00 2001 From: Danny Tiesling Date: Fri, 23 Feb 2024 09:34:29 -0800 Subject: [PATCH 54/74] =?UTF-8?q?=F0=9F=90=9B=20Source=20S3:=20fix=20excep?= =?UTF-8?q?tion=20when=20setting=20CSV=20stream=20delimiter=20to=20`\t`.?= =?UTF-8?q?=20(#35246)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marcos Marx Co-authored-by: marcosmarxm --- .../airbyte_cdk/sources/file_based/config/csv_format.py | 2 ++ .../sources/file_based/config/test_csv_format.py | 7 ++++++- airbyte-integrations/connectors/source-s3/metadata.yaml | 2 +- airbyte-integrations/connectors/source-s3/pyproject.toml | 2 +- docs/integrations/sources/s3.md | 1 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/airbyte-cdk/python/airbyte_cdk/sources/file_based/config/csv_format.py b/airbyte-cdk/python/airbyte_cdk/sources/file_based/config/csv_format.py index fab52aeefd28..bf8a57e73e90 100644 --- a/airbyte-cdk/python/airbyte_cdk/sources/file_based/config/csv_format.py +++ b/airbyte-cdk/python/airbyte_cdk/sources/file_based/config/csv_format.py @@ -150,6 +150,8 @@ class Config(OneOfOptionConfig): @validator("delimiter") def validate_delimiter(cls, v: str) -> str: + if v == r"\t": + return v if len(v) != 1: raise ValueError("delimiter should only be one character") if v in {"\r", "\n"}: diff --git a/airbyte-cdk/python/unit_tests/sources/file_based/config/test_csv_format.py b/airbyte-cdk/python/unit_tests/sources/file_based/config/test_csv_format.py index 4b1b2bb9fcad..1b2d23b810cc 100644 --- a/airbyte-cdk/python/unit_tests/sources/file_based/config/test_csv_format.py +++ b/airbyte-cdk/python/unit_tests/sources/file_based/config/test_csv_format.py @@ -5,7 +5,7 @@ import unittest import pytest -from airbyte_cdk.sources.file_based.config.csv_format import CsvHeaderAutogenerated, CsvHeaderFromCsv, CsvHeaderUserProvided +from airbyte_cdk.sources.file_based.config.csv_format import CsvFormat, CsvHeaderAutogenerated, CsvHeaderFromCsv, CsvHeaderUserProvided from pydantic import ValidationError @@ -26,3 +26,8 @@ def test_given_autogenerated_then_csv_does_not_have_header_row(self) -> None: def test_given_from_csv_then_csv_has_header_row(self) -> None: assert CsvHeaderFromCsv().has_header_row() + + +class CsvDelimiterTest(unittest.TestCase): + def test_tab_delimter(self): + assert CsvFormat(delimiter=r"\t").delimiter == '\\t' diff --git a/airbyte-integrations/connectors/source-s3/metadata.yaml b/airbyte-integrations/connectors/source-s3/metadata.yaml index acbed125e654..055abf46d9f2 100644 --- a/airbyte-integrations/connectors/source-s3/metadata.yaml +++ b/airbyte-integrations/connectors/source-s3/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: file connectorType: source definitionId: 69589781-7828-43c5-9f63-8925b1c1ccc2 - dockerImageTag: 4.5.5 + dockerImageTag: 4.5.6 dockerRepository: airbyte/source-s3 documentationUrl: https://docs.airbyte.com/integrations/sources/s3 githubIssueLabel: source-s3 diff --git a/airbyte-integrations/connectors/source-s3/pyproject.toml b/airbyte-integrations/connectors/source-s3/pyproject.toml index 6f12b067f101..b19e21b9612d 100644 --- a/airbyte-integrations/connectors/source-s3/pyproject.toml +++ b/airbyte-integrations/connectors/source-s3/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "4.5.5" +version = "4.5.6" name = "source-s3" description = "Source implementation for S3." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/s3.md b/docs/integrations/sources/s3.md index ff8263e911c5..0fa3b9dbc96c 100644 --- a/docs/integrations/sources/s3.md +++ b/docs/integrations/sources/s3.md @@ -264,6 +264,7 @@ To perform the text extraction from PDF and Docx files, the connector uses the [ | Version | Date | Pull Request | Subject | |:--------|:-----------|:----------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------| +| 4.5.6 | 2024-02-21 | [35246](https://github.com/airbytehq/airbyte/pull/35246) | Fixes bug that occurred when creating CSV streams with tab delimiter. | | 4.5.5 | 2024-02-18 | [35392](https://github.com/airbytehq/airbyte/pull/35392) | Add support filtering by start date | | 4.5.4 | 2024-02-15 | [35055](https://github.com/airbytehq/airbyte/pull/35055) | Temporarily revert concurrency | | 4.5.3 | 2024-02-12 | [35164](https://github.com/airbytehq/airbyte/pull/35164) | Manage dependencies with Poetry. | From edc58a7875b6ecc18a871bb3613cbffe8a4d303d Mon Sep 17 00:00:00 2001 From: Marco Fontana Date: Fri, 23 Feb 2024 18:43:12 +0000 Subject: [PATCH 55/74] =?UTF-8?q?=F0=9F=90=9B=20Source=20BigQuery:=20fix?= =?UTF-8?q?=20error=20with=20RECORD=20REPEATED=20fields=20=20(#35503)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marcos Marx Co-authored-by: marcosmarxm --- .../connectors/source-bigquery/metadata.yaml | 2 +- .../source/bigquery/BigQuerySource.java | 8 ++- .../BigQuerySourceStructRepeatedTest.java | 56 +++++++++++++++++++ docs/integrations/sources/bigquery.md | 1 + 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 airbyte-integrations/connectors/source-bigquery/src/test-integration/java/io/airbyte/integrations/source/bigquery/BigQuerySourceStructRepeatedTest.java diff --git a/airbyte-integrations/connectors/source-bigquery/metadata.yaml b/airbyte-integrations/connectors/source-bigquery/metadata.yaml index 7bc915c8cb27..e203e3fae69f 100644 --- a/airbyte-integrations/connectors/source-bigquery/metadata.yaml +++ b/airbyte-integrations/connectors/source-bigquery/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: source definitionId: bfd1ddf8-ae8a-4620-b1d7-55597d2ba08c - dockerImageTag: 0.4.1 + dockerImageTag: 0.4.2 dockerRepository: airbyte/source-bigquery documentationUrl: https://docs.airbyte.com/integrations/sources/bigquery githubIssueLabel: source-bigquery diff --git a/airbyte-integrations/connectors/source-bigquery/src/main/java/io/airbyte/integrations/source/bigquery/BigQuerySource.java b/airbyte-integrations/connectors/source-bigquery/src/main/java/io/airbyte/integrations/source/bigquery/BigQuerySource.java index d50d679efe27..6c08f587900a 100644 --- a/airbyte-integrations/connectors/source-bigquery/src/main/java/io/airbyte/integrations/source/bigquery/BigQuerySource.java +++ b/airbyte-integrations/connectors/source-bigquery/src/main/java/io/airbyte/integrations/source/bigquery/BigQuerySource.java @@ -9,6 +9,7 @@ import static io.airbyte.cdk.integrations.source.relationaldb.RelationalDbQueryUtils.queryTable; import com.fasterxml.jackson.databind.JsonNode; +import com.google.cloud.bigquery.Field; import com.google.cloud.bigquery.QueryParameterValue; import com.google.cloud.bigquery.StandardSQLTypeName; import com.google.cloud.bigquery.Table; @@ -128,7 +129,12 @@ protected List>> discoverInternal(fin .name(table.getTableId().getTable()) .fields(Objects.requireNonNull(table.getDefinition().getSchema()).getFields().stream() .map(f -> { - final StandardSQLTypeName standardType = f.getType().getStandardType(); + final StandardSQLTypeName standardType; + if (f.getType().getStandardType() == StandardSQLTypeName.STRUCT && f.getMode() == Field.Mode.REPEATED) { + standardType = StandardSQLTypeName.ARRAY; + } else + standardType = f.getType().getStandardType(); + return new CommonField<>(f.getName(), standardType); }) .collect(Collectors.toList())) diff --git a/airbyte-integrations/connectors/source-bigquery/src/test-integration/java/io/airbyte/integrations/source/bigquery/BigQuerySourceStructRepeatedTest.java b/airbyte-integrations/connectors/source-bigquery/src/test-integration/java/io/airbyte/integrations/source/bigquery/BigQuerySourceStructRepeatedTest.java new file mode 100644 index 000000000000..1d7b03292515 --- /dev/null +++ b/airbyte-integrations/connectors/source-bigquery/src/test-integration/java/io/airbyte/integrations/source/bigquery/BigQuerySourceStructRepeatedTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.source.bigquery; + +import static io.airbyte.integrations.source.bigquery.BigQuerySource.CONFIG_DATASET_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.airbyte.commons.util.MoreIterators; +import io.airbyte.protocol.models.Field; +import io.airbyte.protocol.models.JsonSchemaType; +import io.airbyte.protocol.models.v0.AirbyteMessage; +import io.airbyte.protocol.models.v0.CatalogHelpers; +import io.airbyte.protocol.models.v0.ConfiguredAirbyteCatalog; +import java.sql.SQLException; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class BigQuerySourceStructRepeatedTest extends AbstractBigQuerySourceTest { + + @Override + public void createTable(String datasetId) throws SQLException { + // create column name interval which should be escaped + database.execute("CREATE TABLE " + datasetId + ".struct_repeated(id int64, key_value_pairs ARRAY>);"); + database.execute("INSERT INTO " + datasetId + ".struct_repeated (id, key_value_pairs) VALUES (1, [('a', 0.7), ('b', 0.8), ('c', 1.2)]);"); + } + + @Test + public void testReadSuccess() throws Exception { + final List actualMessages = MoreIterators.toList(new BigQuerySource().read(config, getConfiguredCatalog(), null)); + + ObjectMapper mapper = new ObjectMapper(); + // JsonNode actualObj = mapper.readTree("{\"key_value_pairs\":[{ \"key\": \"a\",\"value\": \"0.7\"}, + // {\"key\": \"b\",\"value\": \"0.8\"}, {\"key\": \"c\",\"value\": \"1.2\"}]}"); + JsonNode actualObj = mapper.readTree("[{ \"key\": \"a\",\"value\": 0.7}, {\"key\": \"b\",\"value\": 0.8}, {\"key\": \"c\",\"value\": 1.2}]"); + + assertNotNull(actualMessages); + assertEquals(1, actualMessages.size()); + + assertNotNull(actualMessages.get(0).getRecord().getData().get("id")); + assertEquals(actualObj, actualMessages.get(0).getRecord().getData().get("key_value_pairs")); + } + + protected ConfiguredAirbyteCatalog getConfiguredCatalog() { + return CatalogHelpers.createConfiguredAirbyteCatalog( + "struct_repeated", + config.get(CONFIG_DATASET_ID).asText(), + Field.of("id", JsonSchemaType.NUMBER), + Field.of("key_value_pairs", JsonSchemaType.ARRAY)); + } + +} diff --git a/docs/integrations/sources/bigquery.md b/docs/integrations/sources/bigquery.md index 9c7eea08c178..b0d73b124294 100644 --- a/docs/integrations/sources/bigquery.md +++ b/docs/integrations/sources/bigquery.md @@ -88,6 +88,7 @@ Once you've configured BigQuery as a source, delete the Service Account Key from | Version | Date | Pull Request | Subject | |:--------|:-----------| :------------------------------------------------------- |:------------------------------------------------------------------------------------------------------------------------------------------| +| 0.4.2 | 2024-02-22 | [35503](https://github.com/airbytehq/airbyte/pull/35503) | Source BigQuery: replicating RECORD REPEATED fields | | 0.4.1 | 2024-01-24 | [34453](https://github.com/airbytehq/airbyte/pull/34453) | bump CDK version | | 0.4.0 | 2023-12-18 | [33484](https://github.com/airbytehq/airbyte/pull/33484) | Remove LEGACY state | | 0.3.0 | 2023-06-26 | [27737](https://github.com/airbytehq/airbyte/pull/27737) | License Update: Elv2 | From e01c0a3780d9468dc06c0dee526c4e1427988b03 Mon Sep 17 00:00:00 2001 From: Stephane Geneix <147216312+stephane-airbyte@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:19:43 -0800 Subject: [PATCH 56/74] re-release source mssql with logger fixes (#35596) --- airbyte-integrations/connectors/source-mssql/metadata.yaml | 2 +- docs/integrations/sources/mssql.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mssql/metadata.yaml b/airbyte-integrations/connectors/source-mssql/metadata.yaml index 1d13ccd7e9da..69ff2c08b161 100644 --- a/airbyte-integrations/connectors/source-mssql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mssql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: b5ea17b1-f170-46dc-bc31-cc744ca984c1 - dockerImageTag: 3.7.2 + dockerImageTag: 3.7.3 dockerRepository: airbyte/source-mssql documentationUrl: https://docs.airbyte.com/integrations/sources/mssql githubIssueLabel: source-mssql diff --git a/docs/integrations/sources/mssql.md b/docs/integrations/sources/mssql.md index 60dec7024ee9..164b087f6fdf 100644 --- a/docs/integrations/sources/mssql.md +++ b/docs/integrations/sources/mssql.md @@ -342,7 +342,8 @@ WHERE actor_definition_id ='b5ea17b1-f170-46dc-bc31-cc744ca984c1' AND (configura | Version | Date | Pull Request | Subject | |:--------|:-----------|:------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| -| 3.7.2 | 2024-02-21 | [35368](https://github.com/airbytehq/airbyte/pull/35368) | Change query syntax to make it compatible with Azure Synapse. | +| 3.7.3 | 2024-02-23 | [35596](https://github.com/airbytehq/airbyte/pull/35596) | Fix a logger issue | +| 3.7.2 | 2024-02-21 | [35368](https://github.com/airbytehq/airbyte/pull/35368) | Change query syntax to make it compatible with Azure SQL Managed Instance. | | 3.7.1 | 2024-02-20 | [35405](https://github.com/airbytehq/airbyte/pull/35405) | Change query syntax to make it compatible with Azure Synapse. | | 3.7.0 | 2024-01-30 | [33311](https://github.com/airbytehq/airbyte/pull/33311) | Source mssql with checkpointing initial sync. | | 3.6.1 | 2024-01-26 | [34573](https://github.com/airbytehq/airbyte/pull/34573) | Adopt CDK v0.16.0. | From c379a7bd352868da6539b03ed06a0c57a8acc9c1 Mon Sep 17 00:00:00 2001 From: "Roman Yermilov [GL]" <86300758+roman-yermilov-gl@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:21:25 +0100 Subject: [PATCH 57/74] Source File: change header=0 to header=null in docs (#35595) CI tests failed because the version was not incremented, despite only a single line being altered in the documentation. This change is minor and can be safely merged. --- airbyte-integrations/connectors/source-file/poetry.lock | 1 + airbyte-integrations/connectors/source-file/pyproject.toml | 2 +- docs/integrations/sources/file.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-file/poetry.lock b/airbyte-integrations/connectors/source-file/poetry.lock index 1a9e63d72152..976dee468500 100644 --- a/airbyte-integrations/connectors/source-file/poetry.lock +++ b/airbyte-integrations/connectors/source-file/poetry.lock @@ -2109,6 +2109,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, diff --git a/airbyte-integrations/connectors/source-file/pyproject.toml b/airbyte-integrations/connectors/source-file/pyproject.toml index 90eff4930cef..3e1f83564b84 100644 --- a/airbyte-integrations/connectors/source-file/pyproject.toml +++ b/airbyte-integrations/connectors/source-file/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "0.3.16" +version = "0.4.0" name = "source-file" description = "Source implementation for File" authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/file.md b/docs/integrations/sources/file.md index 4d4a66eac643..a2fef7e3bbf4 100644 --- a/docs/integrations/sources/file.md +++ b/docs/integrations/sources/file.md @@ -104,6 +104,7 @@ For example, if the format `CSV` is selected, then options from the [read_csv](h - It is therefore possible to customize the `delimiter` (or `sep`) to in case of tab separated files. - Header line can be ignored with `header=0` and customized with `names` +- If a file has no header, it is required to set `header=null`; otherwise, the first record will be missing - Parse dates for in specified columns - etc From 9ff81e3025a7c12b3214112ae4916effd9f8f291 Mon Sep 17 00:00:00 2001 From: Serhii Lazebnyi <53845333+lazebnyi@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:26:04 +0100 Subject: [PATCH 58/74] Changed tag to low code (#35594) CI tests failed because the version was not incremented. This change is minor and can be safely merged. --- .../connectors/source-intercom/metadata.yaml | 2 +- .../connectors/source-intercom/poetry.lock | 36 +++++++++---------- .../connectors/source-intercom/pyproject.toml | 2 +- .../connectors/source-monday/metadata.yaml | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/airbyte-integrations/connectors/source-intercom/metadata.yaml b/airbyte-integrations/connectors/source-intercom/metadata.yaml index 6f0e44543d07..c2af6045c305 100644 --- a/airbyte-integrations/connectors/source-intercom/metadata.yaml +++ b/airbyte-integrations/connectors/source-intercom/metadata.yaml @@ -36,5 +36,5 @@ data: - companies supportLevel: certified tags: - - language:python + - language:low-code metadataSpecVersion: "1.0" diff --git a/airbyte-integrations/connectors/source-intercom/poetry.lock b/airbyte-integrations/connectors/source-intercom/poetry.lock index 09045c77ecbc..3afe43237c13 100644 --- a/airbyte-integrations/connectors/source-intercom/poetry.lock +++ b/airbyte-integrations/connectors/source-intercom/poetry.lock @@ -640,13 +640,13 @@ files = [ [[package]] name = "pytest" -version = "8.0.0" +version = "8.0.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-8.0.1-py3-none-any.whl", hash = "sha256:3e4f16fe1c0a9dc9d9389161c127c3edc5d810c38d6793042fb81d9f48a59fca"}, + {file = "pytest-8.0.1.tar.gz", hash = "sha256:267f6563751877d772019b13aacbe4e860d73fe8f651f28112e9ac37de7513ae"}, ] [package.dependencies] @@ -785,13 +785,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-cache" -version = "1.1.1" +version = "1.2.0" description = "A persistent cache for python requests" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8" files = [ - {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"}, - {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"}, + {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"}, + {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"}, ] [package.dependencies] @@ -803,15 +803,15 @@ url-normalize = ">=1.4" urllib3 = ">=1.25.5" [package.extras] -all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] bson = ["bson (>=0.5)"] -docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] json = ["ujson (>=5.4)"] mongodb = ["pymongo (>=3)"] redis = ["redis (>=3)"] security = ["itsdangerous (>=2.0)"] -yaml = ["pyyaml (>=5.4)"] +yaml = ["pyyaml (>=6.0.1)"] [[package]] name = "requests-mock" @@ -834,19 +834,19 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -897,13 +897,13 @@ six = "*" [[package]] name = "urllib3" -version = "2.2.0" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, - {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.extras] diff --git a/airbyte-integrations/connectors/source-intercom/pyproject.toml b/airbyte-integrations/connectors/source-intercom/pyproject.toml index 57ad7cbabb4a..24942ecbbb9c 100644 --- a/airbyte-integrations/connectors/source-intercom/pyproject.toml +++ b/airbyte-integrations/connectors/source-intercom/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "0.5.1" +version = "0.6.0" name = "source-intercom" description = "Source implementation for Intercom Yaml." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-monday/metadata.yaml b/airbyte-integrations/connectors/source-monday/metadata.yaml index 919c28575e39..abda37283e00 100644 --- a/airbyte-integrations/connectors/source-monday/metadata.yaml +++ b/airbyte-integrations/connectors/source-monday/metadata.yaml @@ -46,5 +46,5 @@ data: releaseStage: generally_available supportLevel: certified tags: - - language:python + - language:low-code metadataSpecVersion: "1.0" From 5d99614fc0f99d3755b39f9d008874210417b0a8 Mon Sep 17 00:00:00 2001 From: pmossman Date: Fri, 23 Feb 2024 19:40:55 +0000 Subject: [PATCH 59/74] Bump Airbyte version from 0.50.52 to 0.50.53 --- .bumpversion.cfg | 2 +- gradle.properties | 2 +- run-ab-platform.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d2eea00484cb..b86cdb84f909 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.50.52 +current_version = 0.50.53 commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-[a-z]+)? diff --git a/gradle.properties b/gradle.properties index c8acd92dea64..83533849f296 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION=0.50.52 +VERSION=0.50.53 # NOTE: some of these values are overwritten in CI! # NOTE: if you want to override this for your local machine, set overrides in ~/.gradle/gradle.properties diff --git a/run-ab-platform.sh b/run-ab-platform.sh index b3f9e270dea5..040575e8d91c 100755 --- a/run-ab-platform.sh +++ b/run-ab-platform.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION=0.50.52 +VERSION=0.50.53 # Run away from anything even a little scary set -o nounset # -u exit if a variable is not set set -o errexit # -f exit for any command failure" From a13bd80f481087cd183a0241f87ff87a801b9c55 Mon Sep 17 00:00:00 2001 From: Gireesh Sreepathi Date: Fri, 23 Feb 2024 12:30:10 -0800 Subject: [PATCH 60/74] Destination Postgres: CDK T+D initial state gathering (#35385) Signed-off-by: Gireesh Sreepathi --- airbyte-cdk/java/airbyte-cdk/README.md | 2 + .../src/main/resources/version.properties | 2 +- .../jdbc/AbstractJdbcDestination.java | 2 +- .../build.gradle | 2 +- .../metadata.yaml | 2 +- .../destination-postgres/build.gradle | 2 +- .../destination-postgres/metadata.yaml | 2 +- .../postgres/PostgresDestination.java | 8 +++ .../PostgresDestinationHandler.java | 51 +++++++++++++++++++ .../typing_deduping/PostgresSqlGenerator.java | 38 -------------- .../PostgresSqlGeneratorIntegrationTest.java | 39 ++++---------- .../AbstractPostgresTypingDedupingTest.java | 2 +- docs/integrations/destinations/postgres.md | 3 +- 13 files changed, 80 insertions(+), 75 deletions(-) create mode 100644 airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresDestinationHandler.java diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index f7a2891b540e..fee7d0f96374 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -166,6 +166,8 @@ MavenLocal debugging steps: | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.23.2 | 2024-02-22 | [\#35385](https://github.com/airbytehq/airbyte/pull/35342) | Bugfix: inverted logic of disableTypeDedupe flag | +| 0.23.1 | 2024-02-22 | [\#35527](https://github.com/airbytehq/airbyte/pull/35527) | reduce shutdown timeouts | | 0.23.0 | 2024-02-22 | [\#35342](https://github.com/airbytehq/airbyte/pull/35342) | Consolidate and perform upfront gathering of DB metadata state | | 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Reduce CDC state compression limit to 1MB | | 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties index 4433e215f812..b0d83063013b 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties @@ -1 +1 @@ -version=0.23.0 +version=0.23.2 diff --git a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java index c060133a5546..b12fd56c93f7 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java +++ b/airbyte-cdk/java/airbyte-cdk/db-destinations/src/main/java/io/airbyte/cdk/integrations/destination/jdbc/AbstractJdbcDestination.java @@ -317,7 +317,7 @@ private TyperDeduper getV2TyperDeduper(final JsonNode config, final ConfiguredAi final var migrator = new JdbcV1V2Migrator(namingResolver, database, databaseName); final NoopV2TableMigrator v2TableMigrator = new NoopV2TableMigrator(); final DestinationHandler destinationHandler = getDestinationHandler(databaseName, database); - final boolean disableTypeDedupe = !config.has(DISABLE_TYPE_DEDUPE) || config.get(DISABLE_TYPE_DEDUPE).asBoolean(false); + final boolean disableTypeDedupe = config.has(DISABLE_TYPE_DEDUPE) && config.get(DISABLE_TYPE_DEDUPE).asBoolean(false); final TyperDeduper typerDeduper; if (disableTypeDedupe) { typerDeduper = new NoOpTyperDeduperWithV1V2Migrations(sqlGenerator, destinationHandler, parsedCatalog, migrator, v2TableMigrator); diff --git a/airbyte-integrations/connectors/destination-postgres-strict-encrypt/build.gradle b/airbyte-integrations/connectors/destination-postgres-strict-encrypt/build.gradle index 87d5e2b99a77..60e06e23de2d 100644 --- a/airbyte-integrations/connectors/destination-postgres-strict-encrypt/build.gradle +++ b/airbyte-integrations/connectors/destination-postgres-strict-encrypt/build.gradle @@ -3,7 +3,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.20.4' + cdkVersionRequired = '0.23.2' features = ['db-destinations', 'typing-deduping', 'datastore-postgres'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/destination-postgres-strict-encrypt/metadata.yaml b/airbyte-integrations/connectors/destination-postgres-strict-encrypt/metadata.yaml index fb475fa2995e..43e8aa23e427 100644 --- a/airbyte-integrations/connectors/destination-postgres-strict-encrypt/metadata.yaml +++ b/airbyte-integrations/connectors/destination-postgres-strict-encrypt/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 25c5221d-dce2-4163-ade9-739ef790f503 - dockerImageTag: 2.0.0 + dockerImageTag: 2.0.1 dockerRepository: airbyte/destination-postgres-strict-encrypt documentationUrl: https://docs.airbyte.com/integrations/destinations/postgres githubIssueLabel: destination-postgres diff --git a/airbyte-integrations/connectors/destination-postgres/build.gradle b/airbyte-integrations/connectors/destination-postgres/build.gradle index 54398f71bd38..ab746b991351 100644 --- a/airbyte-integrations/connectors/destination-postgres/build.gradle +++ b/airbyte-integrations/connectors/destination-postgres/build.gradle @@ -3,7 +3,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.20.4' + cdkVersionRequired = '0.23.2' features = ['db-destinations', 'datastore-postgres', 'typing-deduping'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/destination-postgres/metadata.yaml b/airbyte-integrations/connectors/destination-postgres/metadata.yaml index d380f44acd77..af88d008829f 100644 --- a/airbyte-integrations/connectors/destination-postgres/metadata.yaml +++ b/airbyte-integrations/connectors/destination-postgres/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 25c5221d-dce2-4163-ade9-739ef790f503 - dockerImageTag: 2.0.0 + dockerImageTag: 2.0.1 dockerRepository: airbyte/destination-postgres documentationUrl: https://docs.airbyte.com/integrations/destinations/postgres githubIssueLabel: destination-postgres diff --git a/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/PostgresDestination.java b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/PostgresDestination.java index 62e975dbee86..93c51df74259 100644 --- a/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/PostgresDestination.java +++ b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/PostgresDestination.java @@ -14,13 +14,16 @@ import com.google.common.collect.ImmutableMap; import io.airbyte.cdk.db.factory.DataSourceFactory; import io.airbyte.cdk.db.factory.DatabaseDriver; +import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.db.jdbc.JdbcUtils; import io.airbyte.cdk.integrations.base.Destination; import io.airbyte.cdk.integrations.base.IntegrationRunner; import io.airbyte.cdk.integrations.base.ssh.SshWrappedDestination; import io.airbyte.cdk.integrations.destination.jdbc.AbstractJdbcDestination; +import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.commons.json.Jsons; +import io.airbyte.integrations.destination.postgres.typing_deduping.PostgresDestinationHandler; import io.airbyte.integrations.destination.postgres.typing_deduping.PostgresSqlGenerator; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -127,6 +130,11 @@ protected JdbcSqlGenerator getSqlGenerator() { return new PostgresSqlGenerator(new PostgresSQLNameTransformer()); } + @Override + protected JdbcDestinationHandler getDestinationHandler(String databaseName, JdbcDatabase database) { + return new PostgresDestinationHandler(databaseName, database); + } + @Override public boolean isV2Destination() { return true; diff --git a/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresDestinationHandler.java b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresDestinationHandler.java new file mode 100644 index 000000000000..21cc549b3d38 --- /dev/null +++ b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresDestinationHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.destination.postgres.typing_deduping; + +import io.airbyte.cdk.db.jdbc.JdbcDatabase; +import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; +import io.airbyte.integrations.base.destination.typing_deduping.Array; +import io.airbyte.integrations.base.destination.typing_deduping.Struct; +import io.airbyte.integrations.base.destination.typing_deduping.Union; +import io.airbyte.integrations.base.destination.typing_deduping.UnsupportedOneOf; + +public class PostgresDestinationHandler extends JdbcDestinationHandler { + + public PostgresDestinationHandler(String databaseName, JdbcDatabase jdbcDatabase) { + super(databaseName, jdbcDatabase); + } + + @Override + protected String toJdbcTypeName(AirbyteType airbyteType) { + // This is mostly identical to the postgres implementation, but swaps jsonb to super + if (airbyteType instanceof final AirbyteProtocolType airbyteProtocolType) { + return toJdbcTypeName(airbyteProtocolType); + } + return switch (airbyteType.getTypeName()) { + case Struct.TYPE, UnsupportedOneOf.TYPE, Array.TYPE -> "jsonb"; + // No nested Unions supported so this will definitely not result in infinite recursion. + case Union.TYPE -> toJdbcTypeName(((Union) airbyteType).chooseType()); + default -> throw new IllegalArgumentException("Unsupported AirbyteType: " + airbyteType); + }; + } + + private String toJdbcTypeName(final AirbyteProtocolType airbyteProtocolType) { + return switch (airbyteProtocolType) { + case STRING -> "varchar"; + case NUMBER -> "numeric"; + case INTEGER -> "int8"; + case BOOLEAN -> "bool"; + case TIMESTAMP_WITH_TIMEZONE -> "timestamptz"; + case TIMESTAMP_WITHOUT_TIMEZONE -> "timestamp"; + case TIME_WITH_TIMEZONE -> "timetz"; + case TIME_WITHOUT_TIMEZONE -> "time"; + case DATE -> "date"; + case UNKNOWN -> "jsonb"; + }; + } + +} diff --git a/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGenerator.java b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGenerator.java index 0918226b3227..9d7217e3f826 100644 --- a/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGenerator.java +++ b/airbyte-integrations/connectors/destination-postgres/src/main/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGenerator.java @@ -20,10 +20,7 @@ import static org.jooq.impl.DSL.rowNumber; import static org.jooq.impl.DSL.val; -import com.google.common.collect.ImmutableMap; -import io.airbyte.cdk.integrations.base.JavaBaseConstants; import io.airbyte.cdk.integrations.destination.NamingConventionTransformer; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; @@ -37,7 +34,6 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -54,13 +50,6 @@ public class PostgresSqlGenerator extends JdbcSqlGenerator { public static final DataType JSONB_TYPE = new DefaultDataType<>(null, Object.class, "jsonb"); - private static final Map POSTGRES_TYPE_NAME_TO_JDBC_TYPE = ImmutableMap.of( - "numeric", "decimal", - "int8", "bigint", - "bool", "boolean", - "timestamptz", "timestamp with time zone", - "timetz", "time with time zone"); - public PostgresSqlGenerator(final NamingConventionTransformer namingTransformer) { super(namingTransformer); } @@ -309,29 +298,6 @@ protected Field getRowNumber(final List primaryKeys, final Op .orderBy(orderedFields).as(ROW_NUMBER_COLUMN_NAME); } - @Override - public boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final TableDefinition existingTable) { - // Check that the columns match, with special handling for the metadata columns. - // This is mostly identical to the redshift implementation, but swaps super to jsonb - final LinkedHashMap intendedColumns = stream.columns().entrySet().stream() - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey().name(), toDialectType(column.getValue()).getTypeName()), - LinkedHashMap::putAll); - final LinkedHashMap actualColumns = existingTable.columns().entrySet().stream() - .filter(column -> JavaBaseConstants.V2_FINAL_TABLE_METADATA_COLUMNS.stream() - .noneMatch(airbyteColumnName -> airbyteColumnName.equals(column.getKey()))) - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey(), jdbcTypeNameFromPostgresTypeName(column.getValue().type())), - LinkedHashMap::putAll); - - final boolean sameColumns = actualColumns.equals(intendedColumns) - && "varchar".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_RAW_ID).type()) - && "timestamptz".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT).type()) - && "jsonb".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_META).type()); - - return sameColumns; - } - /** * Extract a raw field, leaving it as jsonb */ @@ -343,8 +309,4 @@ private Field jsonTypeof(final Field field) { return function("JSONB_TYPEOF", SQLDataType.VARCHAR, field); } - private static String jdbcTypeNameFromPostgresTypeName(final String redshiftType) { - return POSTGRES_TYPE_NAME_TO_JDBC_TYPE.getOrDefault(redshiftType, redshiftType); - } - } diff --git a/airbyte-integrations/connectors/destination-postgres/src/test-integration/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGeneratorIntegrationTest.java b/airbyte-integrations/connectors/destination-postgres/src/test-integration/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGeneratorIntegrationTest.java index 3f744c846b08..6efac136e4c3 100644 --- a/airbyte-integrations/connectors/destination-postgres/src/test-integration/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGeneratorIntegrationTest.java +++ b/airbyte-integrations/connectors/destination-postgres/src/test-integration/java/io/airbyte/integrations/destination/postgres/typing_deduping/PostgresSqlGeneratorIntegrationTest.java @@ -5,24 +5,23 @@ package io.airbyte.integrations.destination.postgres.typing_deduping; import static io.airbyte.integrations.destination.postgres.typing_deduping.PostgresSqlGenerator.JSONB_TYPE; -import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import com.fasterxml.jackson.databind.JsonNode; import io.airbyte.cdk.db.jdbc.DefaultJdbcDatabase; import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.db.jdbc.JdbcUtils; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; -import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.cdk.integrations.standardtest.destination.typing_deduping.JdbcSqlGeneratorIntegrationTest; import io.airbyte.integrations.base.destination.typing_deduping.DestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialState; import io.airbyte.integrations.base.destination.typing_deduping.Sql; import io.airbyte.integrations.destination.postgres.PostgresDestination; import io.airbyte.integrations.destination.postgres.PostgresSQLNameTransformer; import io.airbyte.integrations.destination.postgres.PostgresTestDatabase; -import java.util.Optional; +import java.util.List; import javax.sql.DataSource; import org.jooq.DataType; import org.jooq.Field; @@ -76,8 +75,8 @@ protected JdbcSqlGenerator getSqlGenerator() { } @Override - protected DestinationHandler getDestinationHandler() { - return new JdbcDestinationHandler(databaseName, database); + protected DestinationHandler getDestinationHandler() { + return new PostgresDestinationHandler(databaseName, database); } @Override @@ -96,29 +95,11 @@ public void testCreateTableIncremental() throws Exception { final Sql sql = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(sql); - final Optional existingTable = destinationHandler.findExistingTable(incrementalDedupStream.id()); - - assertTrue(existingTable.isPresent()); - assertAll( - () -> assertEquals("varchar", existingTable.get().columns().get("_airbyte_raw_id").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("_airbyte_extracted_at").type()), - () -> assertEquals("jsonb", existingTable.get().columns().get("_airbyte_meta").type()), - () -> assertEquals("int8", existingTable.get().columns().get("id1").type()), - () -> assertEquals("int8", existingTable.get().columns().get("id2").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("updated_at").type()), - () -> assertEquals("jsonb", existingTable.get().columns().get("struct").type()), - () -> assertEquals("jsonb", existingTable.get().columns().get("array").type()), - () -> assertEquals("varchar", existingTable.get().columns().get("string").type()), - () -> assertEquals("numeric", existingTable.get().columns().get("number").type()), - () -> assertEquals("int8", existingTable.get().columns().get("integer").type()), - () -> assertEquals("bool", existingTable.get().columns().get("boolean").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("timestamp_with_timezone").type()), - () -> assertEquals("timestamp", existingTable.get().columns().get("timestamp_without_timezone").type()), - () -> assertEquals("timetz", existingTable.get().columns().get("time_with_timezone").type()), - () -> assertEquals("time", existingTable.get().columns().get("time_without_timezone").type()), - () -> assertEquals("date", existingTable.get().columns().get("date").type()), - () -> assertEquals("jsonb", existingTable.get().columns().get("unknown").type())); - // TODO assert on table indexing, etc. + List initialStates = destinationHandler.gatherInitialState(List.of(incrementalDedupStream)); + assertEquals(1, initialStates.size()); + final DestinationInitialState initialState = initialStates.getFirst(); + assertTrue(initialState.isFinalTablePresent()); + assertFalse(initialState.isSchemaMismatch()); } } diff --git a/airbyte-integrations/connectors/destination-postgres/src/testFixtures/java/io/airbyte/integrations/destination/postgres/typing_deduping/AbstractPostgresTypingDedupingTest.java b/airbyte-integrations/connectors/destination-postgres/src/testFixtures/java/io/airbyte/integrations/destination/postgres/typing_deduping/AbstractPostgresTypingDedupingTest.java index 50b1da44fa6c..128d8d2de1cf 100644 --- a/airbyte-integrations/connectors/destination-postgres/src/testFixtures/java/io/airbyte/integrations/destination/postgres/typing_deduping/AbstractPostgresTypingDedupingTest.java +++ b/airbyte-integrations/connectors/destination-postgres/src/testFixtures/java/io/airbyte/integrations/destination/postgres/typing_deduping/AbstractPostgresTypingDedupingTest.java @@ -44,7 +44,7 @@ private String generateBigString() { } @Override - protected SqlGenerator getSqlGenerator() { + protected SqlGenerator getSqlGenerator() { return new PostgresSqlGenerator(new PostgresSQLNameTransformer()); } diff --git a/docs/integrations/destinations/postgres.md b/docs/integrations/destinations/postgres.md index eb07756183d4..50bd15cc864a 100644 --- a/docs/integrations/destinations/postgres.md +++ b/docs/integrations/destinations/postgres.md @@ -193,6 +193,7 @@ Now that you have set up the Postgres destination connector, check out the follo | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------| +| 2.0.1 | 2024-02-22 | [35385](https://github.com/airbytehq/airbyte/pull/35385) | Upgrade CDK to 0.23.0; Gathering required initial state upfront | | 2.0.0 | 2024-02-09 | [35042](https://github.com/airbytehq/airbyte/pull/35042) | GA release V2 destinations format. | | 0.6.3 | 2024-02-06 | [34891](https://github.com/airbytehq/airbyte/pull/34891) | Remove varchar limit, use system defaults | | 0.6.2 | 2024-01-30 | [34683](https://github.com/airbytehq/airbyte/pull/34683) | CDK Upgrade 0.16.3; Fix dependency mismatches in slf4j lib | @@ -220,4 +221,4 @@ Now that you have set up the Postgres destination connector, check out the follo | 0.3.13 | 2021-12-01 | [\#8371](https://github.com/airbytehq/airbyte/pull/8371) | Fixed incorrect handling "\n" in ssh key | | 0.3.12 | 2021-11-08 | [\#7719](https://github.com/airbytehq/airbyte/pull/7719) | Improve handling of wide rows by buffering records based on their byte size rather than their count | | 0.3.11 | 2021-09-07 | [\#5743](https://github.com/airbytehq/airbyte/pull/5743) | Add SSH Tunnel support | -| 0.3.10 | 2021-08-11 | [\#5336](https://github.com/airbytehq/airbyte/pull/5336) | Destination Postgres: fix \u0000\(NULL\) value processing | \ No newline at end of file +| 0.3.10 | 2021-08-11 | [\#5336](https://github.com/airbytehq/airbyte/pull/5336) | Destination Postgres: fix \u0000\(NULL\) value processing | From f6aa9e5f6431f9daf5c9c463557751d3f056fa73 Mon Sep 17 00:00:00 2001 From: Gireesh Sreepathi Date: Fri, 23 Feb 2024 12:57:41 -0800 Subject: [PATCH 61/74] Destination Snowflake: CDK T+D initial state refactor (#35456) Signed-off-by: Gireesh Sreepathi --- .../destination-snowflake/build.gradle | 2 +- .../destination-snowflake/metadata.yaml | 2 +- .../SnowflakeInternalStagingDestination.java | 12 +- .../typing_deduping/SnowflakeColumn.java | 11 - .../SnowflakeColumnDefinition.java | 19 -- .../SnowflakeDestinationHandler.java | 246 ++++++++++++++---- .../SnowflakeSqlGenerator.java | 40 +-- .../SnowflakeTableDefinition.java | 14 - .../SnowflakeV1V2Migrator.java | 29 +-- .../SnowflakeV2TableMigrator.java | 44 +--- .../AbstractSnowflakeTypingDedupingTest.java | 2 +- .../SnowflakeSqlGeneratorIntegrationTest.java | 13 +- docs/integrations/destinations/snowflake.md | 3 +- 13 files changed, 238 insertions(+), 199 deletions(-) delete mode 100644 airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumn.java delete mode 100644 airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumnDefinition.java delete mode 100644 airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeTableDefinition.java diff --git a/airbyte-integrations/connectors/destination-snowflake/build.gradle b/airbyte-integrations/connectors/destination-snowflake/build.gradle index 3cc7265e2df9..b84e054c0609 100644 --- a/airbyte-integrations/connectors/destination-snowflake/build.gradle +++ b/airbyte-integrations/connectors/destination-snowflake/build.gradle @@ -3,7 +3,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.20.9' + cdkVersionRequired = '0.23.2' features = ['db-destinations', 's3-destinations', 'typing-deduping'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/destination-snowflake/metadata.yaml b/airbyte-integrations/connectors/destination-snowflake/metadata.yaml index 021cfd26e685..d39c5a8c9669 100644 --- a/airbyte-integrations/connectors/destination-snowflake/metadata.yaml +++ b/airbyte-integrations/connectors/destination-snowflake/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 424892c4-daac-4491-b35d-c6688ba547ba - dockerImageTag: 3.5.13 + dockerImageTag: 3.5.14 dockerRepository: airbyte/destination-snowflake documentationUrl: https://docs.airbyte.com/integrations/destinations/snowflake githubIssueLabel: destination-snowflake diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/SnowflakeInternalStagingDestination.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/SnowflakeInternalStagingDestination.java index 472c8d5dec8a..253212ecf628 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/SnowflakeInternalStagingDestination.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/SnowflakeInternalStagingDestination.java @@ -13,6 +13,7 @@ import io.airbyte.cdk.integrations.base.TypingAndDedupingFlag; import io.airbyte.cdk.integrations.destination.NamingConventionTransformer; import io.airbyte.cdk.integrations.destination.jdbc.AbstractJdbcDestination; +import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory; import io.airbyte.commons.json.Jsons; @@ -129,6 +130,11 @@ protected JdbcSqlGenerator getSqlGenerator() { throw new UnsupportedOperationException("Snowflake does not yet use the native JDBC DV2 interface"); } + @Override + protected JdbcDestinationHandler getDestinationHandler(String databaseName, JdbcDatabase database) { + throw new UnsupportedOperationException("Snowflake does not yet use the native JDBC DV2 interface"); + } + @Override public SerializedAirbyteMessageConsumer getSerializedMessageConsumer(final JsonNode config, final ConfiguredAirbyteCatalog catalog, @@ -156,13 +162,11 @@ public SerializedAirbyteMessageConsumer getSerializedMessageConsumer(final JsonN final SnowflakeV1V2Migrator migrator = new SnowflakeV1V2Migrator(getNamingResolver(), database, databaseName); final SnowflakeV2TableMigrator v2TableMigrator = new SnowflakeV2TableMigrator(database, databaseName, sqlGenerator, snowflakeDestinationHandler); final boolean disableTypeDedupe = config.has(DISABLE_TYPE_DEDUPE) && config.get(DISABLE_TYPE_DEDUPE).asBoolean(false); - final int defaultThreadCount = 8; if (disableTypeDedupe) { - typerDeduper = new NoOpTyperDeduperWithV1V2Migrations<>(sqlGenerator, snowflakeDestinationHandler, parsedCatalog, migrator, v2TableMigrator, - defaultThreadCount); + typerDeduper = new NoOpTyperDeduperWithV1V2Migrations(sqlGenerator, snowflakeDestinationHandler, parsedCatalog, migrator, v2TableMigrator); } else { typerDeduper = - new DefaultTyperDeduper<>(sqlGenerator, snowflakeDestinationHandler, parsedCatalog, migrator, v2TableMigrator, defaultThreadCount); + new DefaultTyperDeduper(sqlGenerator, snowflakeDestinationHandler, parsedCatalog, migrator, v2TableMigrator); } return StagingConsumerFactory.builder( diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumn.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumn.java deleted file mode 100644 index 8415fedf587c..000000000000 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumn.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.integrations.destination.snowflake.typing_deduping; - -/** - * type is notably _not_ a {@link net.snowflake.client.jdbc.SnowflakeType}. That enum doesn't - * contain all the types that snowflake supports (specifically NUMBER). - */ -public record SnowflakeColumn(String name, String type) {} diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumnDefinition.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumnDefinition.java deleted file mode 100644 index 06be84ffe67f..000000000000 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeColumnDefinition.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.integrations.destination.snowflake.typing_deduping; - -/** - * isNullable is only used to execute a migration away from an older version of - * destination-snowflake, where we created PK columns as NOT NULL. This caused a lot of problems - * because many sources emit null PKs. We may want to remove this field eventually. - */ -public record SnowflakeColumnDefinition(String type, boolean isNullable) { - - @Deprecated - public boolean isNullable() { - return isNullable; - } - -} diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeDestinationHandler.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeDestinationHandler.java index 7afa49a48cc4..5bfeb5d6b25e 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeDestinationHandler.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeDestinationHandler.java @@ -4,24 +4,46 @@ package io.airbyte.integrations.destination.snowflake.typing_deduping; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_META; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.COLUMN_NAME_AB_RAW_ID; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.V2_FINAL_TABLE_METADATA_COLUMNS; + +import com.fasterxml.jackson.databind.JsonNode; import io.airbyte.cdk.db.jdbc.JdbcDatabase; -import io.airbyte.integrations.base.destination.typing_deduping.DestinationHandler; +import io.airbyte.cdk.integrations.destination.jdbc.ColumnDefinition; +import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; +import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; +import io.airbyte.integrations.base.destination.typing_deduping.Array; +import io.airbyte.integrations.base.destination.typing_deduping.ColumnId; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialState; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialStateImpl; +import io.airbyte.integrations.base.destination.typing_deduping.InitialRawTableState; import io.airbyte.integrations.base.destination.typing_deduping.Sql; +import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig; import io.airbyte.integrations.base.destination.typing_deduping.StreamId; +import io.airbyte.integrations.base.destination.typing_deduping.Struct; +import io.airbyte.integrations.base.destination.typing_deduping.Union; +import io.airbyte.integrations.base.destination.typing_deduping.UnsupportedOneOf; import java.sql.ResultSet; import java.sql.SQLException; import java.time.Instant; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import net.snowflake.client.jdbc.SnowflakeSQLException; import org.apache.commons.text.StringSubstitutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SnowflakeDestinationHandler implements DestinationHandler { +public class SnowflakeDestinationHandler extends JdbcDestinationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SnowflakeDestinationHandler.class); public static final String EXCEPTION_COMMON_PREFIX = "JavaScript execution error: Uncaught Execution of multiple statements failed on statement"; @@ -30,60 +52,74 @@ public class SnowflakeDestinationHandler implements DestinationHandler findExistingTable(final StreamId id) throws SQLException { - // The obvious database.getMetaData().getColumns() solution doesn't work, because JDBC translates - // VARIANT as VARCHAR - final LinkedHashMap columns = database.queryJsons( - """ - SELECT column_name, data_type, is_nullable - FROM information_schema.columns - WHERE table_catalog = ? - AND table_schema = ? - AND table_name = ? - ORDER BY ordinal_position; - """, - databaseName.toUpperCase(), - id.finalNamespace().toUpperCase(), - id.finalName().toUpperCase()).stream() - .collect(LinkedHashMap::new, - (map, row) -> map.put( - row.get("COLUMN_NAME").asText(), - new SnowflakeColumnDefinition(row.get("DATA_TYPE").asText(), fromSnowflakeBoolean(row.get("IS_NULLABLE").asText()))), - LinkedHashMap::putAll); - if (columns.isEmpty()) { - return Optional.empty(); - } else { - return Optional.of(new SnowflakeTableDefinition(columns)); + public static LinkedHashMap> findExistingTables(final JdbcDatabase database, + final String databaseName, + final List streamIds) + throws SQLException { + final LinkedHashMap> existingTables = new LinkedHashMap<>(); + final String paramHolder = String.join(",", Collections.nCopies(streamIds.size(), "?")); + // convert list stream to array + final String[] namespaces = streamIds.stream().map(StreamId::finalNamespace).toArray(String[]::new); + final String[] names = streamIds.stream().map(StreamId::finalName).toArray(String[]::new); + final String query = """ + SELECT table_schema, table_name, column_name, data_type, is_nullable + FROM information_schema.columns + WHERE table_catalog = ? + AND table_schema IN (%s) + AND table_name IN (%s) + ORDER BY table_schema, table_name, ordinal_position; + """.formatted(paramHolder, paramHolder); + final String[] bindValues = new String[streamIds.size() * 2 + 1]; + bindValues[0] = databaseName.toUpperCase(); + System.arraycopy(namespaces, 0, bindValues, 1, namespaces.length); + System.arraycopy(names, 0, bindValues, namespaces.length + 1, names.length); + final List results = database.queryJsons(query, bindValues); + for (final JsonNode result : results) { + final String tableSchema = result.get("TABLE_SCHEMA").asText(); + final String tableName = result.get("TABLE_NAME").asText(); + final String columnName = result.get("COLUMN_NAME").asText(); + final String dataType = result.get("DATA_TYPE").asText(); + final String isNullable = result.get("IS_NULLABLE").asText(); + final TableDefinition tableDefinition = existingTables + .computeIfAbsent(tableSchema, k -> new LinkedHashMap<>()) + .computeIfAbsent(tableName, k -> new TableDefinition(new LinkedHashMap<>())); + tableDefinition.columns().put(columnName, new ColumnDefinition(columnName, dataType, 0, fromIsNullableIsoString(isNullable))); } + return existingTables; } - @Override - public LinkedHashMap findExistingFinalTables(final List list) throws Exception { - return null; - } - - @Override - public boolean isFinalTableEmpty(final StreamId id) throws SQLException { - final int rowCount = database.queryInt( - """ - SELECT row_count - FROM information_schema.tables - WHERE table_catalog = ? - AND table_schema = ? - AND table_name = ? - """, - databaseName.toUpperCase(), - id.finalNamespace().toUpperCase(), - id.finalName().toUpperCase()); - return rowCount == 0; + private LinkedHashMap> getFinalTableRowCount(final List streamIds) throws SQLException { + final LinkedHashMap> tableRowCounts = new LinkedHashMap<>(); + final String paramHolder = String.join(",", Collections.nCopies(streamIds.size(), "?")); + // convert list stream to array + final String[] namespaces = streamIds.stream().map(StreamId::finalNamespace).toArray(String[]::new); + final String[] names = streamIds.stream().map(StreamId::finalName).toArray(String[]::new); + final String query = """ + SELECT table_schema, table_name, row_count + FROM information_schema.tables + WHERE table_catalog = ? + AND table_schema IN (%s) + AND table_name IN (%s) + """.formatted(paramHolder, paramHolder); + final String[] bindValues = new String[streamIds.size() * 2 + 1]; + bindValues[0] = databaseName.toUpperCase(); + System.arraycopy(namespaces, 0, bindValues, 1, namespaces.length); + System.arraycopy(names, 0, bindValues, namespaces.length + 1, names.length); + final List results = database.queryJsons(query, bindValues); + for (final JsonNode result : results) { + final String tableSchema = result.get("TABLE_SCHEMA").asText(); + final String tableName = result.get("TABLE_NAME").asText(); + final int rowCount = result.get("ROW_COUNT").asInt(); + tableRowCounts.computeIfAbsent(tableSchema, k -> new LinkedHashMap<>()).put(tableName, rowCount); + } + return tableRowCounts; } - @Override public InitialRawTableState getInitialRawTableState(final StreamId id) throws Exception { final ResultSet tables = database.getMetaData().getTables( databaseName, @@ -158,12 +194,116 @@ public void execute(final Sql sql) throws Exception { } } - /** - * In snowflake information_schema tables, booleans return "YES" and "NO", which DataBind doesn't - * know how to use - */ - private boolean fromSnowflakeBoolean(final String input) { - return input.equalsIgnoreCase("yes"); + private Set getPks(final StreamConfig stream) { + return stream.primaryKey() != null ? stream.primaryKey().stream().map(ColumnId::name).collect(Collectors.toSet()) : Collections.emptySet(); + } + + private boolean isAirbyteRawIdColumnMatch(final TableDefinition existingTable) { + final String abRawIdColumnName = COLUMN_NAME_AB_RAW_ID.toUpperCase(); + return existingTable.columns().containsKey(abRawIdColumnName) && + toJdbcTypeName(AirbyteProtocolType.STRING).equals(existingTable.columns().get(abRawIdColumnName).type()); + } + + private boolean isAirbyteExtractedAtColumnMatch(final TableDefinition existingTable) { + final String abExtractedAtColumnName = COLUMN_NAME_AB_EXTRACTED_AT.toUpperCase(); + return existingTable.columns().containsKey(abExtractedAtColumnName) && + toJdbcTypeName(AirbyteProtocolType.TIMESTAMP_WITH_TIMEZONE).equals(existingTable.columns().get(abExtractedAtColumnName).type()); + } + + private boolean isAirbyteMetaColumnMatch(TableDefinition existingTable) { + final String abMetaColumnName = COLUMN_NAME_AB_META.toUpperCase(); + return existingTable.columns().containsKey(abMetaColumnName) && + "VARIANT".equals(existingTable.columns().get(abMetaColumnName).type()); + } + + protected boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final TableDefinition existingTable) { + final Set pks = getPks(stream); + // This is same as JdbcDestinationHandler#existingSchemaMatchesStreamConfig with upper case + // conversion. + // TODO: Unify this using name transformer or something. + if (!isAirbyteRawIdColumnMatch(existingTable) || + !isAirbyteExtractedAtColumnMatch(existingTable) || + !isAirbyteMetaColumnMatch(existingTable)) { + // Missing AB meta columns from final table, we need them to do proper T+D so trigger soft-reset + return false; + } + final LinkedHashMap intendedColumns = stream.columns().entrySet().stream() + .collect(LinkedHashMap::new, + (map, column) -> map.put(column.getKey().name(), toJdbcTypeName(column.getValue())), + LinkedHashMap::putAll); + + // Filter out Meta columns since they don't exist in stream config. + final LinkedHashMap actualColumns = existingTable.columns().entrySet().stream() + .filter(column -> V2_FINAL_TABLE_METADATA_COLUMNS.stream().map(String::toUpperCase) + .noneMatch(airbyteColumnName -> airbyteColumnName.equals(column.getKey()))) + .collect(LinkedHashMap::new, + (map, column) -> map.put(column.getKey(), column.getValue().type()), + LinkedHashMap::putAll); + // soft-resetting https://github.com/airbytehq/airbyte/pull/31082 + @SuppressWarnings("deprecation") + final boolean hasPksWithNonNullConstraint = existingTable.columns().entrySet().stream() + .anyMatch(c -> pks.contains(c.getKey()) && !c.getValue().isNullable()); + + return !hasPksWithNonNullConstraint + && actualColumns.equals(intendedColumns); + + } + + @Override + public List gatherInitialState(List streamConfigs) throws Exception { + List streamIds = streamConfigs.stream().map(StreamConfig::id).toList(); + final LinkedHashMap> existingTables = findExistingTables(database, databaseName, streamIds); + final LinkedHashMap> tableRowCounts = getFinalTableRowCount(streamIds); + return streamConfigs.stream().map(streamConfig -> { + try { + final String namespace = streamConfig.id().finalNamespace().toUpperCase(); + final String name = streamConfig.id().finalName().toUpperCase(); + boolean isSchemaMismatch = false; + boolean isFinalTableEmpty = true; + boolean isFinalTablePresent = existingTables.containsKey(namespace) && existingTables.get(namespace).containsKey(name); + boolean hasRowCount = tableRowCounts.containsKey(namespace) && tableRowCounts.get(namespace).containsKey(name); + if (isFinalTablePresent) { + final TableDefinition existingTable = existingTables.get(namespace).get(name); + isSchemaMismatch = !existingSchemaMatchesStreamConfig(streamConfig, existingTable); + isFinalTableEmpty = hasRowCount && tableRowCounts.get(namespace).get(name) == 0; + } + final InitialRawTableState initialRawTableState = getInitialRawTableState(streamConfig.id()); + return new DestinationInitialStateImpl(streamConfig, isFinalTablePresent, initialRawTableState, isSchemaMismatch, isFinalTableEmpty); + } catch (Exception e) { + throw new RuntimeException(e); + } + }).collect(Collectors.toList()); + } + + @Override + protected String toJdbcTypeName(AirbyteType airbyteType) { + if (airbyteType instanceof final AirbyteProtocolType p) { + return toJdbcTypeName(p); + } + + return switch (airbyteType.getTypeName()) { + case Struct.TYPE -> "OBJECT"; + case Array.TYPE -> "ARRAY"; + case UnsupportedOneOf.TYPE -> "VARIANT"; + case Union.TYPE -> toJdbcTypeName(((Union) airbyteType).chooseType()); + default -> throw new IllegalArgumentException("Unrecognized type: " + airbyteType.getTypeName()); + }; + } + + private String toJdbcTypeName(final AirbyteProtocolType airbyteProtocolType) { + return switch (airbyteProtocolType) { + case STRING -> "TEXT"; + case NUMBER -> "FLOAT"; + case INTEGER -> "NUMBER"; + case BOOLEAN -> "BOOLEAN"; + case TIMESTAMP_WITH_TIMEZONE -> "TIMESTAMP_TZ"; + case TIMESTAMP_WITHOUT_TIMEZONE -> "TIMESTAMP_NTZ"; + // If you change this - also change the logic in extractAndCast + case TIME_WITH_TIMEZONE -> "TEXT"; + case TIME_WITHOUT_TIMEZONE -> "TIME"; + case DATE -> "DATE"; + case UNKNOWN -> "VARIANT"; + }; } } diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGenerator.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGenerator.java index 88733c74315d..37b0bdaefff8 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGenerator.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGenerator.java @@ -21,22 +21,18 @@ import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig; import io.airbyte.integrations.base.destination.typing_deduping.StreamId; import io.airbyte.integrations.base.destination.typing_deduping.Struct; -import io.airbyte.integrations.base.destination.typing_deduping.TableNotMigratedException; import io.airbyte.integrations.base.destination.typing_deduping.Union; import io.airbyte.integrations.base.destination.typing_deduping.UnsupportedOneOf; import io.airbyte.protocol.models.v0.DestinationSyncMode; import java.time.Instant; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringSubstitutor; -public class SnowflakeSqlGenerator implements SqlGenerator { +public class SnowflakeSqlGenerator implements SqlGenerator { public static final String QUOTE = "\""; @@ -134,36 +130,6 @@ public Sql createTable(final StreamConfig stream, final String suffix, final boo """)); } - @Override - public boolean existingSchemaMatchesStreamConfig(final StreamConfig stream, final SnowflakeTableDefinition existingTable) - throws TableNotMigratedException { - final Set pks = getPks(stream); - - // Check that the columns match, with special handling for the metadata columns. - final LinkedHashMap intendedColumns = stream.columns().entrySet().stream() - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey().name(), toDialectType(column.getValue())), - LinkedHashMap::putAll); - final LinkedHashMap actualColumns = existingTable.columns().entrySet().stream() - .filter(column -> JavaBaseConstants.V2_FINAL_TABLE_METADATA_COLUMNS.stream().map(String::toUpperCase) - .noneMatch(airbyteColumnName -> airbyteColumnName.equals(column.getKey()))) - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey(), column.getValue().type()), - LinkedHashMap::putAll); - // soft-resetting https://github.com/airbytehq/airbyte/pull/31082 - @SuppressWarnings("deprecation") - final boolean hasPksWithNonNullConstraint = existingTable.columns().entrySet().stream() - .anyMatch(c -> pks.contains(c.getKey()) && !c.getValue().isNullable()); - - final boolean sameColumns = actualColumns.equals(intendedColumns) - && !hasPksWithNonNullConstraint - && "TEXT".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_RAW_ID.toUpperCase()).type()) - && "TIMESTAMP_TZ".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT.toUpperCase()).type()) - && "VARIANT".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_META.toUpperCase()).type()); - - return sameColumns; - } - @Override public Sql updateTable(final StreamConfig stream, final String finalSuffix, @@ -552,8 +518,4 @@ public static String escapeSingleQuotedString(final String str) { .replace("'", "\\'"); } - private static Set getPks(final StreamConfig stream) { - return stream.primaryKey() != null ? stream.primaryKey().stream().map(ColumnId::name).collect(Collectors.toSet()) : Collections.emptySet(); - } - } diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeTableDefinition.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeTableDefinition.java deleted file mode 100644 index 2535d9004b13..000000000000 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeTableDefinition.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.integrations.destination.snowflake.typing_deduping; - -import java.util.LinkedHashMap; - -/** - * @param columns Map from column name to type. Type is a plain string because - * {@link net.snowflake.client.jdbc.SnowflakeType} doesn't actually have all the types that - * Snowflake supports. - */ -public record SnowflakeTableDefinition(LinkedHashMap columns) {} diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV1V2Migrator.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV1V2Migrator.java index aa6eba7f7f96..3226afa58337 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV1V2Migrator.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV1V2Migrator.java @@ -4,8 +4,12 @@ package io.airbyte.integrations.destination.snowflake.typing_deduping; +import static io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler.*; + import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.integrations.destination.NamingConventionTransformer; +import io.airbyte.cdk.integrations.destination.jdbc.ColumnDefinition; +import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.integrations.base.destination.typing_deduping.BaseDestinationV1V2Migrator; import io.airbyte.integrations.base.destination.typing_deduping.CollectionUtils; import io.airbyte.integrations.base.destination.typing_deduping.NamespacedTableName; @@ -15,7 +19,7 @@ import java.util.Optional; import lombok.SneakyThrows; -public class SnowflakeV1V2Migrator extends BaseDestinationV1V2Migrator { +public class SnowflakeV1V2Migrator extends BaseDestinationV1V2Migrator { private final NamingConventionTransformer namingConventionTransformer; @@ -48,18 +52,18 @@ protected boolean doesAirbyteInternalNamespaceExist(final StreamConfig streamCon } @Override - protected boolean schemaMatchesExpectation(final SnowflakeTableDefinition existingTable, final Collection columns) { + protected boolean schemaMatchesExpectation(final TableDefinition existingTable, final Collection columns) { return CollectionUtils.containsAllIgnoreCase(existingTable.columns().keySet(), columns); } @SneakyThrows @Override - protected Optional getTableIfExists(final String namespace, final String tableName) throws Exception { - // TODO this is mostly copied from SnowflakeDestinationHandler#findExistingTable, we should probably - // reuse this logic + protected Optional getTableIfExists(final String namespace, final String tableName) throws Exception { + // TODO this looks similar to SnowflakeDestinationHandler#findExistingTables, with a twist; + // databaseName not upper-cased and rawNamespace and rawTableName as-is (no uppercase). // The obvious database.getMetaData().getColumns() solution doesn't work, because JDBC translates // VARIANT as VARCHAR - final LinkedHashMap columns = + final LinkedHashMap columns = database.queryJsons( """ SELECT column_name, data_type, is_nullable @@ -75,12 +79,13 @@ protected Optional getTableIfExists(final String names .stream() .collect(LinkedHashMap::new, (map, row) -> map.put(row.get("COLUMN_NAME").asText(), - new SnowflakeColumnDefinition(row.get("DATA_TYPE").asText(), fromSnowflakeBoolean(row.get("IS_NULLABLE").asText()))), + new ColumnDefinition(row.get("COLUMN_NAME").asText(), row.get("DATA_TYPE").asText(), 0, + fromIsNullableIsoString(row.get("IS_NULLABLE").asText()))), LinkedHashMap::putAll); if (columns.isEmpty()) { return Optional.empty(); } else { - return Optional.of(new SnowflakeTableDefinition(columns)); + return Optional.of(new TableDefinition(columns)); } } @@ -101,12 +106,4 @@ protected boolean doesValidV1RawTableExist(final String namespace, final String return super.doesValidV1RawTableExist(namespace.toUpperCase(), tableName.toUpperCase()); } - /** - * In snowflake information_schema tables, booleans return "YES" and "NO", which DataBind doesn't - * know how to use - */ - private boolean fromSnowflakeBoolean(final String input) { - return input.equalsIgnoreCase("yes"); - } - } diff --git a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV2TableMigrator.java b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV2TableMigrator.java index 9e04ec3b6f22..eef75f86c7bf 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV2TableMigrator.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeV2TableMigrator.java @@ -9,6 +9,7 @@ import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.integrations.base.TypingAndDedupingFlag; +import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig; import io.airbyte.integrations.base.destination.typing_deduping.StreamId; import io.airbyte.integrations.base.destination.typing_deduping.TypeAndDedupeTransaction; @@ -16,6 +17,7 @@ import io.airbyte.protocol.models.v0.DestinationSyncMode; import java.sql.SQLException; import java.util.LinkedHashMap; +import java.util.List; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,8 +50,8 @@ public void migrateIfNecessary(final StreamConfig streamConfig) throws Exception streamConfig.id().originalName(), rawNamespace); final boolean syncModeRequiresMigration = streamConfig.destinationSyncMode() != DestinationSyncMode.OVERWRITE; - final boolean existingTableCaseSensitiveExists = findExistingTable_caseSensitive(caseSensitiveStreamId).isPresent(); - final boolean existingTableUppercaseDoesNotExist = !handler.findExistingTable(streamConfig.id()).isPresent(); + final boolean existingTableCaseSensitiveExists = findExistingTable(caseSensitiveStreamId).isPresent(); + final boolean existingTableUppercaseDoesNotExist = findExistingTable(streamConfig.id()).isEmpty(); LOGGER.info( "Checking whether upcasing migration is necessary for {}.{}. Sync mode requires migration: {}; existing case-sensitive table exists: {}; existing uppercased table does not exist: {}", streamConfig.id().originalNamespace(), @@ -87,41 +89,15 @@ private static String escapeIdentifier_caseSensitive(final String identifier) { return identifier.replace("\"", "\"\""); } - // And this was taken from - // https://github.com/airbytehq/airbyte/blob/master/airbyte-integrations/connectors/destination-snowflake/src/main/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeDestinationHandler.java - public Optional findExistingTable_caseSensitive(final StreamId id) throws SQLException { + private Optional findExistingTable(final StreamId id) throws SQLException { // The obvious database.getMetaData().getColumns() solution doesn't work, because JDBC translates // VARIANT as VARCHAR - final LinkedHashMap columns = database.queryJsons( - """ - SELECT column_name, data_type, is_nullable - FROM information_schema.columns - WHERE table_catalog = ? - AND table_schema = ? - AND table_name = ? - ORDER BY ordinal_position; - """, - databaseName.toUpperCase(), - id.finalNamespace(), - id.finalName()).stream() - .collect(LinkedHashMap::new, - (map, row) -> map.put( - row.get("COLUMN_NAME").asText(), - new SnowflakeColumnDefinition(row.get("DATA_TYPE").asText(), fromSnowflakeBoolean(row.get("IS_NULLABLE").asText()))), - LinkedHashMap::putAll); - if (columns.isEmpty()) { - return Optional.empty(); - } else { - return Optional.of(new SnowflakeTableDefinition(columns)); + LinkedHashMap> existingTableMap = + SnowflakeDestinationHandler.findExistingTables(database, databaseName, List.of(id)); + if (existingTableMap.containsKey(id.finalNamespace()) && existingTableMap.get(id.finalNamespace()).containsKey(id.finalName())) { + return Optional.of(existingTableMap.get(id.finalNamespace()).get(id.finalName())); } - } - - /** - * In snowflake information_schema tables, booleans return "YES" and "NO", which DataBind doesn't - * know how to use - */ - private boolean fromSnowflakeBoolean(String input) { - return input.equalsIgnoreCase("yes"); + return Optional.empty(); } } diff --git a/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/AbstractSnowflakeTypingDedupingTest.java b/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/AbstractSnowflakeTypingDedupingTest.java index a7aac9cef7cc..2c502d1c1ac9 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/AbstractSnowflakeTypingDedupingTest.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/AbstractSnowflakeTypingDedupingTest.java @@ -107,7 +107,7 @@ protected void globalTeardown() throws Exception { } @Override - protected SqlGenerator getSqlGenerator() { + protected SqlGenerator getSqlGenerator() { return new SnowflakeSqlGenerator(); } diff --git a/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGeneratorIntegrationTest.java b/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGeneratorIntegrationTest.java index 13338a83a03e..bf204e1909d7 100644 --- a/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGeneratorIntegrationTest.java +++ b/airbyte-integrations/connectors/destination-snowflake/src/test-integration/java/io/airbyte/integrations/destination/snowflake/typing_deduping/SnowflakeSqlGeneratorIntegrationTest.java @@ -22,6 +22,7 @@ import io.airbyte.commons.io.IOs; import io.airbyte.commons.json.Jsons; import io.airbyte.integrations.base.destination.typing_deduping.BaseSqlGeneratorIntegrationTest; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialState; import io.airbyte.integrations.base.destination.typing_deduping.Sql; import io.airbyte.integrations.base.destination.typing_deduping.StreamId; import io.airbyte.integrations.destination.snowflake.OssCloudEnvVarConsts; @@ -44,7 +45,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -public class SnowflakeSqlGeneratorIntegrationTest extends BaseSqlGeneratorIntegrationTest { +public class SnowflakeSqlGeneratorIntegrationTest extends BaseSqlGeneratorIntegrationTest { private static String databaseName; private static JdbcDatabase database; @@ -411,8 +412,9 @@ public void ensurePKsAreIndexedUnique() throws Exception { // should be OK with new tables destinationHandler.execute(createTable); - final Optional existingTableA = destinationHandler.findExistingTable(streamId); - assertTrue(generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTableA.get())); + List initialStates = destinationHandler.gatherInitialState(List.of(incrementalDedupStream)); + assertEquals(1, initialStates.size()); + assertFalse(initialStates.get(0).isSchemaMismatch()); destinationHandler.execute(Sql.of("DROP TABLE " + streamId.finalTableId(""))); // Hack the create query to add NOT NULLs to emulate the old behavior @@ -424,8 +426,9 @@ public void ensurePKsAreIndexedUnique() throws Exception { .collect(joining("\r\n"))) .toList()).toList(); destinationHandler.execute(new Sql(createTableModified)); - final Optional existingTableB = destinationHandler.findExistingTable(streamId); - assertFalse(generator.existingSchemaMatchesStreamConfig(incrementalDedupStream, existingTableB.get())); + initialStates = destinationHandler.gatherInitialState(List.of(incrementalDedupStream)); + assertEquals(1, initialStates.size()); + assertTrue(initialStates.get(0).isSchemaMismatch()); } } diff --git a/docs/integrations/destinations/snowflake.md b/docs/integrations/destinations/snowflake.md index f7a6f3e7a95d..39be90148e99 100644 --- a/docs/integrations/destinations/snowflake.md +++ b/docs/integrations/destinations/snowflake.md @@ -246,7 +246,8 @@ Otherwise, make sure to grant the role the required permissions in the desired n | Version | Date | Pull Request | Subject | |:----------------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 3.5.13 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | +| 3.5.14 | 2024-02-22 | [35456](https://github.com/airbytehq/airbyte/pull/35456) | Adopt CDK 0.23.0; Gather initial state upfront, reduce information_schema calls | +| 3.5.13 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 3.5.12 | 2024-02-15 | [35240](https://github.com/airbytehq/airbyte/pull/35240) | Adopt CDK 0.20.9 | | 3.5.11 | 2024-02-12 | [35194](https://github.com/airbytehq/airbyte/pull/35194) | Reorder auth options | | 3.5.10 | 2024-02-12 | [35144](https://github.com/airbytehq/airbyte/pull/35144) | Adopt CDK 0.20.2 | From 399fc3372f96e66ccf03c47768207820aacc6dfc Mon Sep 17 00:00:00 2001 From: Gireesh Sreepathi Date: Fri, 23 Feb 2024 12:58:21 -0800 Subject: [PATCH 62/74] Destination Redshift: CDK T+D initial state refactor (#35354) Signed-off-by: Gireesh Sreepathi --- .../destination-redshift/build.gradle | 2 +- .../destination-redshift/metadata.yaml | 2 +- .../RedshiftStagingS3Destination.java | 6 +- .../RedshiftDestinationHandler.java | 69 ++++--- .../typing_deduping/RedshiftSqlGenerator.java | 39 ---- .../RedshiftDestinationAcceptanceTest.java | 5 - .../AbstractRedshiftTypingDedupingTest.java | 2 +- .../RedshiftSqlGeneratorIntegrationTest.java | 36 +--- docs/integrations/destinations/redshift.md | 183 +++++++++--------- .../core-concepts/typing-deduping.md | 4 +- 10 files changed, 145 insertions(+), 203 deletions(-) diff --git a/airbyte-integrations/connectors/destination-redshift/build.gradle b/airbyte-integrations/connectors/destination-redshift/build.gradle index de1540f7811a..298b24ec4012 100644 --- a/airbyte-integrations/connectors/destination-redshift/build.gradle +++ b/airbyte-integrations/connectors/destination-redshift/build.gradle @@ -4,7 +4,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.20.0' + cdkVersionRequired = '0.23.2' features = ['db-destinations', 's3-destinations', 'typing-deduping'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/destination-redshift/metadata.yaml b/airbyte-integrations/connectors/destination-redshift/metadata.yaml index e32903ada77d..368369cfe5d2 100644 --- a/airbyte-integrations/connectors/destination-redshift/metadata.yaml +++ b/airbyte-integrations/connectors/destination-redshift/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: database connectorType: destination definitionId: f7a7d195-377f-cf5b-70a5-be6b819019dc - dockerImageTag: 2.1.7 + dockerImageTag: 2.1.8 dockerRepository: airbyte/destination-redshift documentationUrl: https://docs.airbyte.com/integrations/destinations/redshift githubIssueLabel: destination-redshift diff --git a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/RedshiftStagingS3Destination.java b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/RedshiftStagingS3Destination.java index f1855447cf3c..16189ce2004b 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/RedshiftStagingS3Destination.java +++ b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/RedshiftStagingS3Destination.java @@ -228,13 +228,11 @@ public SerializedAirbyteMessageConsumer getSerializedMessageConsumer(final JsonN final JdbcV1V2Migrator migrator = new JdbcV1V2Migrator(getNamingResolver(), database, databaseName); final NoopV2TableMigrator v2TableMigrator = new NoopV2TableMigrator(); final boolean disableTypeDedupe = config.has(DISABLE_TYPE_DEDUPE) && config.get(DISABLE_TYPE_DEDUPE).asBoolean(false); - final int defaultThreadCount = 8; if (disableTypeDedupe) { - typerDeduper = new NoOpTyperDeduperWithV1V2Migrations<>(sqlGenerator, redshiftDestinationHandler, parsedCatalog, migrator, v2TableMigrator, - defaultThreadCount); + typerDeduper = new NoOpTyperDeduperWithV1V2Migrations(sqlGenerator, redshiftDestinationHandler, parsedCatalog, migrator, v2TableMigrator); } else { typerDeduper = - new DefaultTyperDeduper<>(sqlGenerator, redshiftDestinationHandler, parsedCatalog, migrator, v2TableMigrator, defaultThreadCount); + new DefaultTyperDeduper(sqlGenerator, redshiftDestinationHandler, parsedCatalog, migrator, v2TableMigrator); } return StagingConsumerFactory.builder( outputRecordCollector, diff --git a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftDestinationHandler.java b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftDestinationHandler.java index a9b0ec0330e0..5a47c2436d00 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftDestinationHandler.java +++ b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftDestinationHandler.java @@ -4,11 +4,17 @@ package io.airbyte.integrations.destination.redshift.typing_deduping; -import com.fasterxml.jackson.databind.JsonNode; +import static io.airbyte.cdk.integrations.base.JavaBaseConstants.*; + import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcDestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; +import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; +import io.airbyte.integrations.base.destination.typing_deduping.Array; import io.airbyte.integrations.base.destination.typing_deduping.Sql; -import io.airbyte.integrations.base.destination.typing_deduping.StreamId; +import io.airbyte.integrations.base.destination.typing_deduping.Struct; +import io.airbyte.integrations.base.destination.typing_deduping.Union; +import io.airbyte.integrations.base.destination.typing_deduping.UnsupportedOneOf; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -49,37 +55,36 @@ public void execute(final Sql sql) throws Exception { } } - /** - * Issuing a select 1 limit 1 query can be expensive, so relying on SVV_TABLE_INFO system table. - * EXPLAIN of the select 1 from table limit 1 query: (seq scan and then limit is applied, read from - * bottom to top) XN Lim it (co st=0. 0 .0.01 rows=1 width=0) -> XN Seq Scan on _airbyte_raw_ users - * (cost=0.00..1000.00 rows=100000 width=0) - * - * @param id - * @return - * @throws Exception - */ @Override - public boolean isFinalTableEmpty(final StreamId id) throws Exception { - // Redshift doesn't have an information_schema.tables table, so we have to use SVV_TABLE_INFO. - // From https://docs.aws.amazon.com/redshift/latest/dg/r_SVV_TABLE_INFO.html: - // > The SVV_TABLE_INFO view doesn't return any information for empty tables. - // So we just query for our specific table, and if we get no rows back, - // then we assume the table is empty. - // Note that because the column names are reserved words (table, schema, database), - // we need to enquote them. - final List query = jdbcDatabase.queryJsons( - """ - SELECT 1 - FROM SVV_TABLE_INFO - WHERE "database" = ? - AND "schema" = ? - AND "table" = ? - """, - databaseName, - id.finalNamespace(), - id.finalName()); - return query.isEmpty(); + protected String toJdbcTypeName(AirbyteType airbyteType) { + // This is mostly identical to the postgres implementation, but swaps jsonb to super + if (airbyteType instanceof final AirbyteProtocolType airbyteProtocolType) { + return toJdbcTypeName(airbyteProtocolType); + } + return switch (airbyteType.getTypeName()) { + case Struct.TYPE, UnsupportedOneOf.TYPE, Array.TYPE -> "super"; + // No nested Unions supported so this will definitely not result in infinite recursion. + case Union.TYPE -> toJdbcTypeName(((Union) airbyteType).chooseType()); + default -> throw new IllegalArgumentException("Unsupported AirbyteType: " + airbyteType); + }; } + private String toJdbcTypeName(final AirbyteProtocolType airbyteProtocolType) { + return switch (airbyteProtocolType) { + case STRING -> "varchar"; + case NUMBER -> "numeric"; + case INTEGER -> "int8"; + case BOOLEAN -> "bool"; + case TIMESTAMP_WITH_TIMEZONE -> "timestamptz"; + case TIMESTAMP_WITHOUT_TIMEZONE -> "timestamp"; + case TIME_WITH_TIMEZONE -> "timetz"; + case TIME_WITHOUT_TIMEZONE -> "time"; + case DATE -> "date"; + case UNKNOWN -> "super"; + }; + } + + // Do not use SVV_TABLE_INFO to get isFinalTableEmpty. + // See https://github.com/airbytehq/airbyte/issues/34357 + } diff --git a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGenerator.java b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGenerator.java index 4c110d7a20cd..37f72c21c9f1 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGenerator.java +++ b/airbyte-integrations/connectors/destination-redshift/src/main/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGenerator.java @@ -16,16 +16,12 @@ import static org.jooq.impl.DSL.rowNumber; import static org.jooq.impl.DSL.val; -import com.google.common.collect.ImmutableMap; -import io.airbyte.cdk.integrations.base.JavaBaseConstants; import io.airbyte.cdk.integrations.destination.NamingConventionTransformer; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteProtocolType; import io.airbyte.integrations.base.destination.typing_deduping.AirbyteType; import io.airbyte.integrations.base.destination.typing_deduping.Array; import io.airbyte.integrations.base.destination.typing_deduping.ColumnId; -import io.airbyte.integrations.base.destination.typing_deduping.StreamConfig; import io.airbyte.integrations.base.destination.typing_deduping.Struct; import io.airbyte.integrations.base.destination.typing_deduping.Union; import io.airbyte.integrations.base.destination.typing_deduping.UnsupportedOneOf; @@ -33,7 +29,6 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import org.jooq.Condition; @@ -47,12 +42,6 @@ public class RedshiftSqlGenerator extends JdbcSqlGenerator { public static final String CASE_STATEMENT_SQL_TEMPLATE = "CASE WHEN {0} THEN {1} ELSE {2} END "; public static final String CASE_STATEMENT_NO_ELSE_SQL_TEMPLATE = "CASE WHEN {0} THEN {1} END "; - private static final Map REDSHIFT_TYPE_NAME_TO_JDBC_TYPE = ImmutableMap.of( - "numeric", "decimal", - "int8", "bigint", - "bool", "boolean", - "timestamptz", "timestamp with time zone", - "timetz", "time with time zone"); private static final String COLUMN_ERROR_MESSAGE_FORMAT = "Problem with `%s`"; private static final String AIRBYTE_META_COLUMN_ERRORS_KEY = "errors"; @@ -168,7 +157,6 @@ Field arrayConcatStmt(final List> arrays) { } Field result = arrays.get(0); - String renderedSql = getDslContext().render(result); for (int i = 1; i < arrays.size(); i++) { // We lose some nice indentation but thats ok. Queryparts // are intentionally rendered here to avoid deep stack for function sql rendering. @@ -199,29 +187,6 @@ protected Field buildAirbyteMetaColumn(final LinkedHashMap intendedColumns = stream.columns().entrySet().stream() - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey().name(), toDialectType(column.getValue()).getTypeName()), - LinkedHashMap::putAll); - final LinkedHashMap actualColumns = existingTable.columns().entrySet().stream() - .filter(column -> JavaBaseConstants.V2_FINAL_TABLE_METADATA_COLUMNS.stream() - .noneMatch(airbyteColumnName -> airbyteColumnName.equals(column.getKey()))) - .collect(LinkedHashMap::new, - (map, column) -> map.put(column.getKey(), jdbcTypeNameFromRedshiftTypeName(column.getValue().type())), - LinkedHashMap::putAll); - - final boolean sameColumns = actualColumns.equals(intendedColumns) - && "varchar".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_RAW_ID).type()) - && "timestamptz".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_EXTRACTED_AT).type()) - && "super".equals(existingTable.columns().get(JavaBaseConstants.COLUMN_NAME_AB_META).type()); - - return sameColumns; - } - /** * Return ROW_NUMBER() OVER (PARTITION BY primaryKeys ORDER BY cursor DESC NULLS LAST, * _airbyte_extracted_at DESC) @@ -265,8 +230,4 @@ public boolean shouldRetry(final Exception e) { return false; } - private static String jdbcTypeNameFromRedshiftTypeName(final String redshiftType) { - return REDSHIFT_TYPE_NAME_TO_JDBC_TYPE.getOrDefault(redshiftType, redshiftType); - } - } diff --git a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/RedshiftDestinationAcceptanceTest.java b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/RedshiftDestinationAcceptanceTest.java index b398c0b9e597..de31216ed222 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/RedshiftDestinationAcceptanceTest.java +++ b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/RedshiftDestinationAcceptanceTest.java @@ -241,9 +241,4 @@ protected int getMaxRecordValueLimit() { return RedshiftSqlOperations.REDSHIFT_VARCHAR_MAX_BYTE_SIZE; } - @Override - protected int getGenerateBigStringAddExtraCharacters() { - return 1; - } - } diff --git a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/AbstractRedshiftTypingDedupingTest.java b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/AbstractRedshiftTypingDedupingTest.java index c5928ab534d6..514fd14363a8 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/AbstractRedshiftTypingDedupingTest.java +++ b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/AbstractRedshiftTypingDedupingTest.java @@ -34,7 +34,7 @@ protected JdbcCompatibleSourceOperations getSourceOperations() { } @Override - protected SqlGenerator getSqlGenerator() { + protected SqlGenerator getSqlGenerator() { return new RedshiftSqlGenerator(new RedshiftSQLNameTransformer()) { // Override only for tests to print formatted SQL. The actual implementation should use unformatted diff --git a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGeneratorIntegrationTest.java b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGeneratorIntegrationTest.java index 1ddca62a2bcd..854fe35cfff6 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGeneratorIntegrationTest.java +++ b/airbyte-integrations/connectors/destination-redshift/src/test-integration/java/io/airbyte/integrations/destination/redshift/typing_deduping/RedshiftSqlGeneratorIntegrationTest.java @@ -6,8 +6,8 @@ import static io.airbyte.cdk.db.jdbc.DateTimeConverter.putJavaSQLTime; import static io.airbyte.integrations.destination.redshift.operations.RedshiftSqlOperations.escapeStringLiteral; -import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import com.fasterxml.jackson.databind.JsonNode; @@ -17,11 +17,11 @@ import io.airbyte.cdk.db.jdbc.JdbcDatabase; import io.airbyte.cdk.db.jdbc.JdbcSourceOperations; import io.airbyte.cdk.db.jdbc.JdbcUtils; -import io.airbyte.cdk.integrations.destination.jdbc.TableDefinition; import io.airbyte.cdk.integrations.destination.jdbc.typing_deduping.JdbcSqlGenerator; import io.airbyte.cdk.integrations.standardtest.destination.typing_deduping.JdbcSqlGeneratorIntegrationTest; import io.airbyte.commons.json.Jsons; import io.airbyte.integrations.base.destination.typing_deduping.DestinationHandler; +import io.airbyte.integrations.base.destination.typing_deduping.DestinationInitialState; import io.airbyte.integrations.base.destination.typing_deduping.Sql; import io.airbyte.integrations.destination.redshift.RedshiftInsertDestination; import io.airbyte.integrations.destination.redshift.RedshiftSQLNameTransformer; @@ -33,7 +33,7 @@ import java.time.LocalDateTime; import java.time.OffsetTime; import java.time.ZoneOffset; -import java.util.Optional; +import java.util.List; import javax.sql.DataSource; import org.jooq.DSLContext; import org.jooq.DataType; @@ -151,7 +151,7 @@ protected DSLContext getDslContext() { } @Override - protected DestinationHandler getDestinationHandler() { + protected DestinationHandler getDestinationHandler() { return new RedshiftDestinationHandler(databaseName, database); } @@ -180,29 +180,11 @@ protected Field toJsonValue(final String valueAsString) { public void testCreateTableIncremental() throws Exception { final Sql sql = generator.createTable(incrementalDedupStream, "", false); destinationHandler.execute(sql); - - final Optional existingTable = destinationHandler.findExistingTable(incrementalDedupStream.id()); - - assertTrue(existingTable.isPresent()); - assertAll( - () -> assertEquals("varchar", existingTable.get().columns().get("_airbyte_raw_id").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("_airbyte_extracted_at").type()), - () -> assertEquals("super", existingTable.get().columns().get("_airbyte_meta").type()), - () -> assertEquals("int8", existingTable.get().columns().get("id1").type()), - () -> assertEquals("int8", existingTable.get().columns().get("id2").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("updated_at").type()), - () -> assertEquals("super", existingTable.get().columns().get("struct").type()), - () -> assertEquals("super", existingTable.get().columns().get("array").type()), - () -> assertEquals("varchar", existingTable.get().columns().get("string").type()), - () -> assertEquals("numeric", existingTable.get().columns().get("number").type()), - () -> assertEquals("int8", existingTable.get().columns().get("integer").type()), - () -> assertEquals("bool", existingTable.get().columns().get("boolean").type()), - () -> assertEquals("timestamptz", existingTable.get().columns().get("timestamp_with_timezone").type()), - () -> assertEquals("timestamp", existingTable.get().columns().get("timestamp_without_timezone").type()), - () -> assertEquals("timetz", existingTable.get().columns().get("time_with_timezone").type()), - () -> assertEquals("time", existingTable.get().columns().get("time_without_timezone").type()), - () -> assertEquals("date", existingTable.get().columns().get("date").type()), - () -> assertEquals("super", existingTable.get().columns().get("unknown").type())); + List initialStates = destinationHandler.gatherInitialState(List.of(incrementalDedupStream)); + assertEquals(1, initialStates.size()); + final DestinationInitialState initialState = initialStates.getFirst(); + assertTrue(initialState.isFinalTablePresent()); + assertFalse(initialState.isSchemaMismatch()); // TODO assert on table clustering, etc. } diff --git a/docs/integrations/destinations/redshift.md b/docs/integrations/destinations/redshift.md index ba51ae50ba1f..c37e01dcbb67 100644 --- a/docs/integrations/destinations/redshift.md +++ b/docs/integrations/destinations/redshift.md @@ -235,94 +235,95 @@ Each stream will be output into its own raw table in Redshift. Each table will c ## Changelog -| Version | Date | Pull Request | Subject | -|:--------|:-----------|:------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 2.1.7 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Switch back to jooq-based sql execution for standard insert | -| 2.1.6 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Update to CDK version 0.17.0 | -| 2.1.5 | 2024-01-30 | [\#34680](https://github.com/airbytehq/airbyte/pull/34680) | Update to CDK version 0.16.3 | -| 2.1.4 | 2024-01-29 | [\#34634](https://github.com/airbytehq/airbyte/pull/34634) | Use lowercase raw schema and table in T+D [CDK changes](https://github.com/airbytehq/airbyte/pull/34533) | -| 2.1.3 | 2024-01-26 | [\#34544](https://github.com/airbytehq/airbyte/pull/34544) | Proper string-escaping in raw tables | -| 2.1.2 | 2024-01-24 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Improve logging for unparseable input | -| 2.1.1 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Improve error reporting | -| 2.1.0 | 2024-01-24 | [\#34467](https://github.com/airbytehq/airbyte/pull/34467) | Upgrade CDK to 0.14.0 | -| 2.0.0 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Destinations V2 | -| 0.8.0 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Upgrade CDK to 0.13.0 | -| 0.7.15 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Update check method with svv_table_info permission check, fix bug where s3 staging files were not being deleted. | -| 0.7.14 | 2024-01-08 | [\#34014](https://github.com/airbytehq/airbyte/pull/34014) | Update order of options in spec | -| 0.7.13 | 2024-01-05 | [\#33948](https://github.com/airbytehq/airbyte/pull/33948) | Fix NPE when prepare tables fail; Add case sensitive session for super; Bastion heartbeats added | -| 0.7.12 | 2024-01-03 | [\#33924](https://github.com/airbytehq/airbyte/pull/33924) | Add new ap-southeast-3 AWS region | -| 0.7.11 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | Internal code structure changes | -| 0.7.10 | 2024-01-04 | [\#33728](https://github.com/airbytehq/airbyte/pull/33728) | Allow users to disable final table creation | -| 0.7.9 | 2024-01-03 | [\#33877](https://github.com/airbytehq/airbyte/pull/33877) | Fix Jooq StackOverflowError | -| 0.7.8 | 2023-12-28 | [\#33788](https://github.com/airbytehq/airbyte/pull/33788) | Thread-safe fix for file part names (s3 staging files) | -| 0.7.7 | 2024-01-04 | [\#33728](https://github.com/airbytehq/airbyte/pull/33728) | Add option to only type and dedupe at the end of the sync | -| 0.7.6 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | Only run T+D on a stream if it had any records during the sync | -| 0.7.5 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation | -| 0.7.4 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Use jdbc common sql implementation | -| 0.7.3 | 2023-12-12 | [\#33367](https://github.com/airbytehq/airbyte/pull/33367) | DV2: fix migration logic | -| 0.7.2 | 2023-12-11 | [\#33335](https://github.com/airbytehq/airbyte/pull/33335) | DV2: improve data type mapping | -| 0.7.1 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | ~DV2: improve data type mapping~ No changes | -| 0.7.0 | 2023-12-05 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Opt in beta for v2 destination | -| 0.6.11 | 2023-11-29 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | Use the new async framework. | -| 0.6.10 | 2023-11-06 | [\#32193](https://github.com/airbytehq/airbyte/pull/32193) | Adopt java CDK version 0.4.1. | -| 0.6.9 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | -| 0.6.8 | 2023-10-10 | [\#31218](https://github.com/airbytehq/airbyte/pull/31218) | Clarify configuration groups | -| 0.6.7 | 2023-10-06 | [\#31153](https://github.com/airbytehq/airbyte/pull/31153) | Increase jvm GC retries | -| 0.6.6 | 2023-10-06 | [\#31129](https://github.com/airbytehq/airbyte/pull/31129) | Reduce async buffer size | -| 0.6.5 | 2023-08-18 | [\#28619](https://github.com/airbytehq/airbyte/pull/29640) | Fix duplicate staging object names in concurrent environment (e.g. async) | -| 0.6.4 | 2023-08-10 | [\#28619](https://github.com/airbytehq/airbyte/pull/28619) | Use async method for staging | -| 0.6.3 | 2023-08-07 | [\#29188](https://github.com/airbytehq/airbyte/pull/29188) | Internal code refactoring | -| 0.6.2 | 2023-07-24 | [\#28618](https://github.com/airbytehq/airbyte/pull/28618) | Add hooks in preparation for destinations v2 implementation | -| 0.6.1 | 2023-07-14 | [\#28345](https://github.com/airbytehq/airbyte/pull/28345) | Increment patch to trigger a rebuild | -| 0.6.0 | 2023-06-27 | [\#27993](https://github.com/airbytehq/airbyte/pull/27993) | destination-redshift will fail syncs if records or properties are too large, rather than silently skipping records and succeeding | -| 0.5.0 | 2023-06-27 | [\#27781](https://github.com/airbytehq/airbyte/pull/27781) | License Update: Elv2 | -| 0.4.9 | 2023-06-21 | [\#27555](https://github.com/airbytehq/airbyte/pull/27555) | Reduce image size | -| 0.4.8 | 2023-05-17 | [\#26165](https://github.com/airbytehq/airbyte/pull/26165) | Internal code change for future development (install normalization packages inside connector) | -| 0.4.7 | 2023-05-01 | [\#25698](https://github.com/airbytehq/airbyte/pull/25698) | Remove old VARCHAR to SUPER migration Java functionality | -| 0.4.6 | 2023-04-27 | [\#25346](https://github.com/airbytehq/airbyte/pull/25346) | Internal code cleanup | -| 0.4.5 | 2023-03-30 | [\#24736](https://github.com/airbytehq/airbyte/pull/24736) | Improve behavior when throttled by AWS API | -| 0.4.4 | 2023-03-29 | [\#24671](https://github.com/airbytehq/airbyte/pull/24671) | Fail faster in certain error cases | -| 0.4.3 | 2023-03-17 | [\#23788](https://github.com/airbytehq/airbyte/pull/23788) | S3-Parquet: added handler to process null values in arrays | -| 0.4.2 | 2023-03-10 | [\#23931](https://github.com/airbytehq/airbyte/pull/23931) | Added support for periodic buffer flush | -| 0.4.1 | 2023-03-10 | [\#23466](https://github.com/airbytehq/airbyte/pull/23466) | Changed S3 Avro type from Int to Long | -| 0.4.0 | 2023-02-28 | [\#23523](https://github.com/airbytehq/airbyte/pull/23523) | Add SSH Bastion Host configuration options | -| 0.3.56 | 2023-01-26 | [\#21890](https://github.com/airbytehq/airbyte/pull/21890) | Fixed configurable parameter for number of file buffers | -| 0.3.55 | 2023-01-26 | [\#20631](https://github.com/airbytehq/airbyte/pull/20631) | Added support for destination checkpointing with staging | -| 0.3.54 | 2023-01-18 | [\#21087](https://github.com/airbytehq/airbyte/pull/21087) | Wrap Authentication Errors as Config Exceptions | -| 0.3.53 | 2023-01-03 | [\#17273](https://github.com/airbytehq/airbyte/pull/17273) | Flatten JSON arrays to fix maximum size check for SUPER field | -| 0.3.52 | 2022-12-30 | [\#20879](https://github.com/airbytehq/airbyte/pull/20879) | Added configurable parameter for number of file buffers (⛔ this version has a bug and will not work; use `0.3.56` instead) | -| 0.3.51 | 2022-10-26 | [\#18434](https://github.com/airbytehq/airbyte/pull/18434) | Fix empty S3 bucket path handling | -| 0.3.50 | 2022-09-14 | [\#15668](https://github.com/airbytehq/airbyte/pull/15668) | Wrap logs in AirbyteLogMessage | -| 0.3.49 | 2022-09-01 | [\#16243](https://github.com/airbytehq/airbyte/pull/16243) | Fix Json to Avro conversion when there is field name clash from combined restrictions (`anyOf`, `oneOf`, `allOf` fields) | -| 0.3.48 | 2022-09-01 | | Added JDBC URL params | -| 0.3.47 | 2022-07-15 | [\#14494](https://github.com/airbytehq/airbyte/pull/14494) | Make S3 output filename configurable. | -| 0.3.46 | 2022-06-27 | [\#14190](https://github.com/airbytehq/airbyte/pull/13916) | Correctly cleanup S3 bucket when using a configured bucket path for S3 staging operations. | -| 0.3.45 | 2022-06-25 | [\#13916](https://github.com/airbytehq/airbyte/pull/13916) | Use the configured bucket path for S3 staging operations. | -| 0.3.44 | 2022-06-24 | [\#14114](https://github.com/airbytehq/airbyte/pull/14114) | Remove "additionalProperties": false from specs for connectors with staging | -| 0.3.43 | 2022-06-24 | [\#13690](https://github.com/airbytehq/airbyte/pull/13690) | Improved discovery for NOT SUPER column | -| 0.3.42 | 2022-06-21 | [\#14013](https://github.com/airbytehq/airbyte/pull/14013) | Add an option to use encryption with staging in Redshift Destination | -| 0.3.40 | 2022-06-17 | [\#13753](https://github.com/airbytehq/airbyte/pull/13753) | Deprecate and remove PART\*SIZE_MB fields from connectors based on StreamTransferManager | -| 0.3.39 | 2022-06-02 | [\#13415](https://github.com/airbytehq/airbyte/pull/13415) | Add dropdown to select Uploading Method.
**PLEASE NOTICE**: After this update your **uploading method** will be set to **Standard**, you will need to reconfigure the method to use **S3 Staging** again. | -| 0.3.37 | 2022-05-23 | [\#13090](https://github.com/airbytehq/airbyte/pull/13090) | Removed redshiftDataTmpTableMode. Some refactoring. | -| 0.3.36 | 2022-05-23 | [\#12820](https://github.com/airbytehq/airbyte/pull/12820) | Improved 'check' operation performance | -| 0.3.35 | 2022-05-18 | [\#12940](https://github.com/airbytehq/airbyte/pull/12940) | Fixed maximum record size for SUPER type | -| 0.3.34 | 2022-05-16 | [\#12869](https://github.com/airbytehq/airbyte/pull/12869) | Fixed NPE in S3 staging check | -| 0.3.33 | 2022-05-04 | [\#12601](https://github.com/airbytehq/airbyte/pull/12601) | Apply buffering strategy for S3 staging | -| 0.3.32 | 2022-04-20 | [\#12085](https://github.com/airbytehq/airbyte/pull/12085) | Fixed bug with switching between INSERT and COPY config | -| 0.3.31 | 2022-04-19 | [\#12064](https://github.com/airbytehq/airbyte/pull/12064) | Added option to support SUPER datatype in \_airbyte_raw\*\*\* table | -| 0.3.29 | 2022-04-05 | [\#11729](https://github.com/airbytehq/airbyte/pull/11729) | Fixed bug with dashes in schema name | -| 0.3.28 | 2022-03-18 | [\#11254](https://github.com/airbytehq/airbyte/pull/11254) | Fixed missing records during S3 staging | -| 0.3.27 | 2022-02-25 | [\#10421](https://github.com/airbytehq/airbyte/pull/10421) | Refactor JDBC parameters handling | -| 0.3.25 | 2022-02-14 | [\#9920](https://github.com/airbytehq/airbyte/pull/9920) | Updated the size of staging files for S3 staging. Also, added closure of S3 writers to staging files when data has been written to an staging file. | -| 0.3.24 | 2022-02-14 | [\#10256](https://github.com/airbytehq/airbyte/pull/10256) | Add `-XX:+ExitOnOutOfMemoryError` JVM option | -| 0.3.23 | 2021-12-16 | [\#8855](https://github.com/airbytehq/airbyte/pull/8855) | Add `purgeStagingData` option to enable/disable deleting the staging data | -| 0.3.22 | 2021-12-15 | [\#8607](https://github.com/airbytehq/airbyte/pull/8607) | Accept a path for the staging data | -| 0.3.21 | 2021-12-10 | [\#8562](https://github.com/airbytehq/airbyte/pull/8562) | Moving classes around for better dependency management | -| 0.3.20 | 2021-11-08 | [\#7719](https://github.com/airbytehq/airbyte/pull/7719) | Improve handling of wide rows by buffering records based on their byte size rather than their count | -| 0.3.19 | 2021-10-21 | [\#7234](https://github.com/airbytehq/airbyte/pull/7234) | Allow SSL traffic only | -| 0.3.17 | 2021-10-12 | [\#6965](https://github.com/airbytehq/airbyte/pull/6965) | Added SSL Support | -| 0.3.16 | 2021-10-11 | [\#6949](https://github.com/airbytehq/airbyte/pull/6949) | Each stream was split into files of 10,000 records each for copying using S3 or GCS | -| 0.3.14 | 2021-10-08 | [\#5924](https://github.com/airbytehq/airbyte/pull/5924) | Fixed AWS S3 Staging COPY is writing records from different table in the same raw table | -| 0.3.13 | 2021-09-02 | [\#5745](https://github.com/airbytehq/airbyte/pull/5745) | Disable STATUPDATE flag when using S3 staging to speed up performance | -| 0.3.12 | 2021-07-21 | [\#3555](https://github.com/airbytehq/airbyte/pull/3555) | Enable partial checkpointing for halfway syncs | -| 0.3.11 | 2021-07-20 | [\#4874](https://github.com/airbytehq/airbyte/pull/4874) | allow `additionalProperties` in connector spec | +| Version | Date | Pull Request | Subject | +|:--------|:-----------|:-----------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.1.8 | 2024-02-09 | [\#35354](https://github.com/airbytehq/airbyte/pull/35354) | Update to CDK 0.23.0; Gather required initial state upfront, remove dependency on svv_table_info for table empty check | +| 2.1.7 | 2024-02-09 | [\#34562](https://github.com/airbytehq/airbyte/pull/34562) | Switch back to jooq-based sql execution for standard insert | +| 2.1.6 | 2024-02-08 | [\#34502](https://github.com/airbytehq/airbyte/pull/34502) | Update to CDK version 0.17.0 | +| 2.1.5 | 2024-01-30 | [\#34680](https://github.com/airbytehq/airbyte/pull/34680) | Update to CDK version 0.16.3 | +| 2.1.4 | 2024-01-29 | [\#34634](https://github.com/airbytehq/airbyte/pull/34634) | Use lowercase raw schema and table in T+D [CDK changes](https://github.com/airbytehq/airbyte/pull/34533) | +| 2.1.3 | 2024-01-26 | [\#34544](https://github.com/airbytehq/airbyte/pull/34544) | Proper string-escaping in raw tables | +| 2.1.2 | 2024-01-24 | [\#34451](https://github.com/airbytehq/airbyte/pull/34451) | Improve logging for unparseable input | +| 2.1.1 | 2024-01-24 | [\#34458](https://github.com/airbytehq/airbyte/pull/34458) | Improve error reporting | +| 2.1.0 | 2024-01-24 | [\#34467](https://github.com/airbytehq/airbyte/pull/34467) | Upgrade CDK to 0.14.0 | +| 2.0.0 | 2024-01-23 | [\#34077](https://github.com/airbytehq/airbyte/pull/34077) | Destinations V2 | +| 0.8.0 | 2024-01-18 | [\#34236](https://github.com/airbytehq/airbyte/pull/34236) | Upgrade CDK to 0.13.0 | +| 0.7.15 | 2024-01-11 | [\#34186](https://github.com/airbytehq/airbyte/pull/34186) | Update check method with svv_table_info permission check, fix bug where s3 staging files were not being deleted. | +| 0.7.14 | 2024-01-08 | [\#34014](https://github.com/airbytehq/airbyte/pull/34014) | Update order of options in spec | +| 0.7.13 | 2024-01-05 | [\#33948](https://github.com/airbytehq/airbyte/pull/33948) | Fix NPE when prepare tables fail; Add case sensitive session for super; Bastion heartbeats added | +| 0.7.12 | 2024-01-03 | [\#33924](https://github.com/airbytehq/airbyte/pull/33924) | Add new ap-southeast-3 AWS region | +| 0.7.11 | 2024-01-04 | [\#33730](https://github.com/airbytehq/airbyte/pull/33730) | Internal code structure changes | +| 0.7.10 | 2024-01-04 | [\#33728](https://github.com/airbytehq/airbyte/pull/33728) | Allow users to disable final table creation | +| 0.7.9 | 2024-01-03 | [\#33877](https://github.com/airbytehq/airbyte/pull/33877) | Fix Jooq StackOverflowError | +| 0.7.8 | 2023-12-28 | [\#33788](https://github.com/airbytehq/airbyte/pull/33788) | Thread-safe fix for file part names (s3 staging files) | +| 0.7.7 | 2024-01-04 | [\#33728](https://github.com/airbytehq/airbyte/pull/33728) | Add option to only type and dedupe at the end of the sync | +| 0.7.6 | 2023-12-20 | [\#33704](https://github.com/airbytehq/airbyte/pull/33704) | Only run T+D on a stream if it had any records during the sync | +| 0.7.5 | 2023-12-18 | [\#33124](https://github.com/airbytehq/airbyte/pull/33124) | Make Schema Creation Separate from Table Creation | +| 0.7.4 | 2023-12-13 | [\#33369](https://github.com/airbytehq/airbyte/pull/33369) | Use jdbc common sql implementation | +| 0.7.3 | 2023-12-12 | [\#33367](https://github.com/airbytehq/airbyte/pull/33367) | DV2: fix migration logic | +| 0.7.2 | 2023-12-11 | [\#33335](https://github.com/airbytehq/airbyte/pull/33335) | DV2: improve data type mapping | +| 0.7.1 | 2023-12-11 | [\#33307](https://github.com/airbytehq/airbyte/pull/33307) | ~DV2: improve data type mapping~ No changes | +| 0.7.0 | 2023-12-05 | [\#32326](https://github.com/airbytehq/airbyte/pull/32326) | Opt in beta for v2 destination | +| 0.6.11 | 2023-11-29 | [\#32888](https://github.com/airbytehq/airbyte/pull/32888) | Use the new async framework. | +| 0.6.10 | 2023-11-06 | [\#32193](https://github.com/airbytehq/airbyte/pull/32193) | Adopt java CDK version 0.4.1. | +| 0.6.9 | 2023-10-10 | [\#31083](https://github.com/airbytehq/airbyte/pull/31083) | Fix precision of numeric values in async destinations | +| 0.6.8 | 2023-10-10 | [\#31218](https://github.com/airbytehq/airbyte/pull/31218) | Clarify configuration groups | +| 0.6.7 | 2023-10-06 | [\#31153](https://github.com/airbytehq/airbyte/pull/31153) | Increase jvm GC retries | +| 0.6.6 | 2023-10-06 | [\#31129](https://github.com/airbytehq/airbyte/pull/31129) | Reduce async buffer size | +| 0.6.5 | 2023-08-18 | [\#28619](https://github.com/airbytehq/airbyte/pull/29640) | Fix duplicate staging object names in concurrent environment (e.g. async) | +| 0.6.4 | 2023-08-10 | [\#28619](https://github.com/airbytehq/airbyte/pull/28619) | Use async method for staging | +| 0.6.3 | 2023-08-07 | [\#29188](https://github.com/airbytehq/airbyte/pull/29188) | Internal code refactoring | +| 0.6.2 | 2023-07-24 | [\#28618](https://github.com/airbytehq/airbyte/pull/28618) | Add hooks in preparation for destinations v2 implementation | +| 0.6.1 | 2023-07-14 | [\#28345](https://github.com/airbytehq/airbyte/pull/28345) | Increment patch to trigger a rebuild | +| 0.6.0 | 2023-06-27 | [\#27993](https://github.com/airbytehq/airbyte/pull/27993) | destination-redshift will fail syncs if records or properties are too large, rather than silently skipping records and succeeding | +| 0.5.0 | 2023-06-27 | [\#27781](https://github.com/airbytehq/airbyte/pull/27781) | License Update: Elv2 | +| 0.4.9 | 2023-06-21 | [\#27555](https://github.com/airbytehq/airbyte/pull/27555) | Reduce image size | +| 0.4.8 | 2023-05-17 | [\#26165](https://github.com/airbytehq/airbyte/pull/26165) | Internal code change for future development (install normalization packages inside connector) | +| 0.4.7 | 2023-05-01 | [\#25698](https://github.com/airbytehq/airbyte/pull/25698) | Remove old VARCHAR to SUPER migration Java functionality | +| 0.4.6 | 2023-04-27 | [\#25346](https://github.com/airbytehq/airbyte/pull/25346) | Internal code cleanup | +| 0.4.5 | 2023-03-30 | [\#24736](https://github.com/airbytehq/airbyte/pull/24736) | Improve behavior when throttled by AWS API | +| 0.4.4 | 2023-03-29 | [\#24671](https://github.com/airbytehq/airbyte/pull/24671) | Fail faster in certain error cases | +| 0.4.3 | 2023-03-17 | [\#23788](https://github.com/airbytehq/airbyte/pull/23788) | S3-Parquet: added handler to process null values in arrays | +| 0.4.2 | 2023-03-10 | [\#23931](https://github.com/airbytehq/airbyte/pull/23931) | Added support for periodic buffer flush | +| 0.4.1 | 2023-03-10 | [\#23466](https://github.com/airbytehq/airbyte/pull/23466) | Changed S3 Avro type from Int to Long | +| 0.4.0 | 2023-02-28 | [\#23523](https://github.com/airbytehq/airbyte/pull/23523) | Add SSH Bastion Host configuration options | +| 0.3.56 | 2023-01-26 | [\#21890](https://github.com/airbytehq/airbyte/pull/21890) | Fixed configurable parameter for number of file buffers | +| 0.3.55 | 2023-01-26 | [\#20631](https://github.com/airbytehq/airbyte/pull/20631) | Added support for destination checkpointing with staging | +| 0.3.54 | 2023-01-18 | [\#21087](https://github.com/airbytehq/airbyte/pull/21087) | Wrap Authentication Errors as Config Exceptions | +| 0.3.53 | 2023-01-03 | [\#17273](https://github.com/airbytehq/airbyte/pull/17273) | Flatten JSON arrays to fix maximum size check for SUPER field | +| 0.3.52 | 2022-12-30 | [\#20879](https://github.com/airbytehq/airbyte/pull/20879) | Added configurable parameter for number of file buffers (⛔ this version has a bug and will not work; use `0.3.56` instead) | +| 0.3.51 | 2022-10-26 | [\#18434](https://github.com/airbytehq/airbyte/pull/18434) | Fix empty S3 bucket path handling | +| 0.3.50 | 2022-09-14 | [\#15668](https://github.com/airbytehq/airbyte/pull/15668) | Wrap logs in AirbyteLogMessage | +| 0.3.49 | 2022-09-01 | [\#16243](https://github.com/airbytehq/airbyte/pull/16243) | Fix Json to Avro conversion when there is field name clash from combined restrictions (`anyOf`, `oneOf`, `allOf` fields) | +| 0.3.48 | 2022-09-01 | | Added JDBC URL params | +| 0.3.47 | 2022-07-15 | [\#14494](https://github.com/airbytehq/airbyte/pull/14494) | Make S3 output filename configurable. | +| 0.3.46 | 2022-06-27 | [\#14190](https://github.com/airbytehq/airbyte/pull/13916) | Correctly cleanup S3 bucket when using a configured bucket path for S3 staging operations. | +| 0.3.45 | 2022-06-25 | [\#13916](https://github.com/airbytehq/airbyte/pull/13916) | Use the configured bucket path for S3 staging operations. | +| 0.3.44 | 2022-06-24 | [\#14114](https://github.com/airbytehq/airbyte/pull/14114) | Remove "additionalProperties": false from specs for connectors with staging | +| 0.3.43 | 2022-06-24 | [\#13690](https://github.com/airbytehq/airbyte/pull/13690) | Improved discovery for NOT SUPER column | +| 0.3.42 | 2022-06-21 | [\#14013](https://github.com/airbytehq/airbyte/pull/14013) | Add an option to use encryption with staging in Redshift Destination | +| 0.3.40 | 2022-06-17 | [\#13753](https://github.com/airbytehq/airbyte/pull/13753) | Deprecate and remove PART\*SIZE_MB fields from connectors based on StreamTransferManager | +| 0.3.39 | 2022-06-02 | [\#13415](https://github.com/airbytehq/airbyte/pull/13415) | Add dropdown to select Uploading Method.
**PLEASE NOTICE**: After this update your **uploading method** will be set to **Standard**, you will need to reconfigure the method to use **S3 Staging** again. | +| 0.3.37 | 2022-05-23 | [\#13090](https://github.com/airbytehq/airbyte/pull/13090) | Removed redshiftDataTmpTableMode. Some refactoring. | +| 0.3.36 | 2022-05-23 | [\#12820](https://github.com/airbytehq/airbyte/pull/12820) | Improved 'check' operation performance | +| 0.3.35 | 2022-05-18 | [\#12940](https://github.com/airbytehq/airbyte/pull/12940) | Fixed maximum record size for SUPER type | +| 0.3.34 | 2022-05-16 | [\#12869](https://github.com/airbytehq/airbyte/pull/12869) | Fixed NPE in S3 staging check | +| 0.3.33 | 2022-05-04 | [\#12601](https://github.com/airbytehq/airbyte/pull/12601) | Apply buffering strategy for S3 staging | +| 0.3.32 | 2022-04-20 | [\#12085](https://github.com/airbytehq/airbyte/pull/12085) | Fixed bug with switching between INSERT and COPY config | +| 0.3.31 | 2022-04-19 | [\#12064](https://github.com/airbytehq/airbyte/pull/12064) | Added option to support SUPER datatype in \_airbyte_raw\*\*\* table | +| 0.3.29 | 2022-04-05 | [\#11729](https://github.com/airbytehq/airbyte/pull/11729) | Fixed bug with dashes in schema name | +| 0.3.28 | 2022-03-18 | [\#11254](https://github.com/airbytehq/airbyte/pull/11254) | Fixed missing records during S3 staging | +| 0.3.27 | 2022-02-25 | [\#10421](https://github.com/airbytehq/airbyte/pull/10421) | Refactor JDBC parameters handling | +| 0.3.25 | 2022-02-14 | [\#9920](https://github.com/airbytehq/airbyte/pull/9920) | Updated the size of staging files for S3 staging. Also, added closure of S3 writers to staging files when data has been written to an staging file. | +| 0.3.24 | 2022-02-14 | [\#10256](https://github.com/airbytehq/airbyte/pull/10256) | Add `-XX:+ExitOnOutOfMemoryError` JVM option | +| 0.3.23 | 2021-12-16 | [\#8855](https://github.com/airbytehq/airbyte/pull/8855) | Add `purgeStagingData` option to enable/disable deleting the staging data | +| 0.3.22 | 2021-12-15 | [\#8607](https://github.com/airbytehq/airbyte/pull/8607) | Accept a path for the staging data | +| 0.3.21 | 2021-12-10 | [\#8562](https://github.com/airbytehq/airbyte/pull/8562) | Moving classes around for better dependency management | +| 0.3.20 | 2021-11-08 | [\#7719](https://github.com/airbytehq/airbyte/pull/7719) | Improve handling of wide rows by buffering records based on their byte size rather than their count | +| 0.3.19 | 2021-10-21 | [\#7234](https://github.com/airbytehq/airbyte/pull/7234) | Allow SSL traffic only | +| 0.3.17 | 2021-10-12 | [\#6965](https://github.com/airbytehq/airbyte/pull/6965) | Added SSL Support | +| 0.3.16 | 2021-10-11 | [\#6949](https://github.com/airbytehq/airbyte/pull/6949) | Each stream was split into files of 10,000 records each for copying using S3 or GCS | +| 0.3.14 | 2021-10-08 | [\#5924](https://github.com/airbytehq/airbyte/pull/5924) | Fixed AWS S3 Staging COPY is writing records from different table in the same raw table | +| 0.3.13 | 2021-09-02 | [\#5745](https://github.com/airbytehq/airbyte/pull/5745) | Disable STATUPDATE flag when using S3 staging to speed up performance | +| 0.3.12 | 2021-07-21 | [\#3555](https://github.com/airbytehq/airbyte/pull/3555) | Enable partial checkpointing for halfway syncs | +| 0.3.11 | 2021-07-20 | [\#4874](https://github.com/airbytehq/airbyte/pull/4874) | allow `additionalProperties` in connector spec | diff --git a/docs/using-airbyte/core-concepts/typing-deduping.md b/docs/using-airbyte/core-concepts/typing-deduping.md index eb606fc3e096..c0c6c57906bd 100644 --- a/docs/using-airbyte/core-concepts/typing-deduping.md +++ b/docs/using-airbyte/core-concepts/typing-deduping.md @@ -114,8 +114,8 @@ observers. This is done for a number of reasons, including: column order and data types of each column. - **Transactional Full Refresh** - In order to keep your final tables consistently useful, when a refresh or reset occurs, airbyte will erase the raw tables, and then build a new tmp final table - first. Only at hte last second will Airbyte swap the old and tmp final tables, usually via a - rename. Otherwise, there would be a period of time where the final table is empty, which could + first. Airbyte attempts to do an atomic swap of old and tmp final tables, usually via a + rename at the last second. Otherwise, there would be a period of time where the final table is empty, which could cause downstream issues. This means that additional permissions, constraints, views, or other rules you apply to the final From b247f899045c8c312a63f0d85e083fc65abc7b9f Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 23 Feb 2024 22:17:48 +0100 Subject: [PATCH 63/74] delete metadata checks workflow (#35580) --- .../workflows/connector_metadata_checks.yml | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/connector_metadata_checks.yml diff --git a/.github/workflows/connector_metadata_checks.yml b/.github/workflows/connector_metadata_checks.yml deleted file mode 100644 index 2af441a2bbe9..000000000000 --- a/.github/workflows/connector_metadata_checks.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Connector Ops CI - Connector Metadata Checks - -on: - pull_request: - paths: - - "airbyte-integrations/connectors/source-**" -jobs: - connector-metadata-checks: - name: "Check Connector Metadata" - runs-on: ubuntu-latest - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Install Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - name: Install ci-connector-ops package - run: | - pip install pipx - pipx ensurepath - pipx install airbyte-ci/connectors/connector_ops/ - - name: Check test strictness level - run: check-test-strictness-level - - name: Check allowed hosts - run: allowed-hosts-checks From 040d3633adfe71c8c3a61685b385e73bcc12291e Mon Sep 17 00:00:00 2001 From: Christo Grabowski <108154848+ChristoGrab@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:11:15 -0500 Subject: [PATCH 64/74] Source Recurly: Enable in registries with updated CDK (#34622) --- .../connectors/source-recurly/Dockerfile | 38 - .../connectors/source-recurly/README.md | 111 +- .../source-recurly/acceptance-test-config.yml | 57 +- .../integration_tests/future_state.json | 132 ++- .../connectors/source-recurly/metadata.yaml | 16 +- .../connectors/source-recurly/poetry.lock | 1045 +++++++++++++++++ .../connectors/source-recurly/pyproject.toml | 29 + .../source-recurly/requirements.txt | 2 - .../connectors/source-recurly/setup.py | 44 - .../schemas/account_coupon_redemptions.json | 27 +- .../source_recurly/schemas/account_notes.json | 14 +- .../source_recurly/schemas/accounts.json | 39 +- .../source_recurly/schemas/billing_infos.json | 195 +-- .../source_recurly/schemas/coupons.json | 187 +-- .../source_recurly/schemas/invoices.json | 54 +- .../source_recurly/schemas/line_items.json | 269 +---- .../schemas/measured_units.json | 3 + .../source_recurly/schemas/plans.json | 45 + .../schemas/shared/account_details.json | 35 + .../schemas/shared/billing_infos.json | 213 ++++ .../schemas/shared/coupon_redemptions.json | 85 ++ .../schemas/shared/coupons.json | 194 +++ .../schemas/shared/external_accounts.json | 24 + .../schemas/shared/line_items.json | 293 +++++ .../schemas/shared/shipping_addresses.json | 91 ++ .../schemas/shared/tax_info.json | 44 + .../schemas/shared/unique_coupons.json | 66 ++ .../source_recurly/schemas/shared/users.json | 33 + .../schemas/shipping_addresses.json | 84 +- .../source_recurly/schemas/subscriptions.json | 174 ++- .../source_recurly/schemas/transactions.json | 96 +- .../schemas/unique_coupons.json | 62 +- .../source-recurly/source_recurly/spec.json | 2 +- docs/integrations/sources/recurly.md | 1 + 34 files changed, 2670 insertions(+), 1134 deletions(-) delete mode 100644 airbyte-integrations/connectors/source-recurly/Dockerfile create mode 100644 airbyte-integrations/connectors/source-recurly/poetry.lock create mode 100644 airbyte-integrations/connectors/source-recurly/pyproject.toml delete mode 100644 airbyte-integrations/connectors/source-recurly/requirements.txt delete mode 100644 airbyte-integrations/connectors/source-recurly/setup.py create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/account_details.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/billing_infos.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupon_redemptions.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupons.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/external_accounts.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/line_items.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/shipping_addresses.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/tax_info.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/unique_coupons.json create mode 100644 airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/users.json diff --git a/airbyte-integrations/connectors/source-recurly/Dockerfile b/airbyte-integrations/connectors/source-recurly/Dockerfile deleted file mode 100644 index 51646e6746f5..000000000000 --- a/airbyte-integrations/connectors/source-recurly/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM python:3.9.11-alpine3.15 as base - -# build and load all requirements -FROM base as builder -WORKDIR /airbyte/integration_code - -# upgrade pip to the latest version -RUN apk --no-cache upgrade \ - && pip install --upgrade pip \ - && apk --no-cache add tzdata build-base - - -COPY setup.py ./ -# install necessary packages to a temporary folder -RUN pip install --prefix=/install . - -# build a clean environment -FROM base -WORKDIR /airbyte/integration_code - -# copy all loaded and built libraries to a pure basic image -COPY --from=builder /install /usr/local -# add default timezone settings -COPY --from=builder /usr/share/zoneinfo/Etc/UTC /etc/localtime -RUN echo "Etc/UTC" > /etc/timezone - -# bash is installed for more convenient debugging. -RUN apk --no-cache add bash - -# copy payload code only -COPY main.py ./ -COPY source_recurly ./source_recurly - -ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" -ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] - -LABEL io.airbyte.version=0.4.1 -LABEL io.airbyte.name=airbyte/source-recurly diff --git a/airbyte-integrations/connectors/source-recurly/README.md b/airbyte-integrations/connectors/source-recurly/README.md index 0b6cedea3f2e..936201b1a143 100644 --- a/airbyte-integrations/connectors/source-recurly/README.md +++ b/airbyte-integrations/connectors/source-recurly/README.md @@ -1,97 +1,104 @@ -# Amazon Seller-Partner Source +# Recurly source connector -This is the repository for the Amazon Seller-Partner source connector, written in Python. -For information about how to use this connector within Airbyte, see [the documentation](https://docs.airbyte.io/integrations/sources/amazon-seller-partner). +This is the repository for the Recurly source connector, written in Python. +For information about how to use this connector within Airbyte, see [the documentation](https://docs.airbyte.io/integrations/sources/recurly). ## Local development ### Prerequisites -**To iterate on this connector, make sure to complete this prerequisites section.** -#### Build & Activate Virtual Environment and install dependencies -From this connector directory, create a virtual environment: -``` -python -m venv .venv -``` +* Python (~=3.9) +* Poetry (~=1.7) - installation instructions [here](https://python-poetry.org/docs/#installation) -This will generate a virtualenv for this module in `.venv/`. Make sure this venv is active in your -development environment of choice. To activate it from the terminal, run: -``` -source .venv/bin/activate -pip install -r requirements.txt +### Installing the connector + +From this connector directory, run: + +```bash +poetry install --with dev ``` -If you are in an IDE, follow your IDE's instructions to activate the virtualenv. -Note that while we are installing dependencies from `requirements.txt`, you should only edit `setup.py` for your dependencies. `requirements.txt` is -used for editable installs (`pip install -e`) to pull in Python dependencies from the monorepo and will call `setup.py`. -If this is mumbo jumbo to you, don't worry about it, just put your deps in `setup.py` but install using `pip install -r requirements.txt` and everything -should work as you expect. +### Creating credentials -#### Create credentials -**If you are a community contributor**, follow the instructions in the [documentation](https://docs.airbyte.io/integrations/sources/amazon-seller-partner) -to generate the necessary credentials. Then create a file `secrets/config.json` conforming to the `source_amazon_seller-partner/integration_tests/spec.json` file. +**If you are a community contributor**, follow the instructions in the [documentation](https://docs.airbyte.io/integrations/sources/recurly) +to generate the necessary credentials. Then create a file `secrets/config.json` conforming to the `source_recurly/spec.json` file. Note that the `secrets` directory is gitignored by default, so there is no danger of accidentally checking in sensitive information. See `integration_tests/sample_config.json` for a sample config file. -**If you are an Airbyte core member**, copy the credentials in Lastpass under the secret name `source amazon-seller-partner test creds` +**If you are an Airbyte core member**, copy the credentials in Lastpass under the secret name `source recurly test creds` and place them into `secrets/config.json`. ### Locally running the connector -``` -python main.py spec -python main.py check --config secrets/config.json -python main.py discover --config secrets/config.json -python main.py read --config secrets/config.json --catalog integration_tests/configured_catalog.json + +```bash +poetry run source-recurly spec +poetry run source-recurly check --config secrets/config.json +poetry run source-recurly discover --config secrets/config.json +poetry run source-recurly read --config secrets/config.json --catalog sample_files/configured_catalog.json ``` -### Locally running the connector docker image +### Running unit tests +To run unit tests locally, from the connector directory run: -#### Build -**Via [`airbyte-ci`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md) (recommended):** ```bash -airbyte-ci connectors --name source-amazon-seller-partner build +poetry run pytest unit_tests ``` -An image will be built with the tag `airbyte/source-amazon-seller-partner:dev`. +### Building the docker image + +1. Install [`airbyte-ci`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md) +2. Run the following command to build the docker image: -**Via `docker build`:** ```bash -docker build -t airbyte/source-amazon-seller-partner:dev . +airbyte-ci connectors --name=source-recurly build ``` -#### Run +An image will be available on your host with the tag `airbyte/source-recurly:dev`. + +### Running the docker container + Then run any of the connector commands as follows: -``` -docker run --rm airbyte/source-amazon-seller-partner:dev spec -docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-amazon-seller-partner:dev check --config /secrets/config.json -docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-amazon-seller-partner:dev discover --config /secrets/config.json -docker run --rm -v $(pwd)/secrets:/secrets -v $(pwd)/integration_tests:/integration_tests airbyte/source-amazon-seller-partner:dev read --config /secrets/config.json --catalog /integration_tests/configured_catalog.json + +```bash +docker run --rm airbyte/source-recurly:dev spec +docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-recurly:dev check --config /secrets/config.json +docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-recurly:dev discover --config /secrets/config.json +docker run --rm -v $(pwd)/secrets:/secrets -v $(pwd)/integration_tests:/integration_tests airbyte/source-recurly:dev read --config /secrets/config.json --catalog /integration_tests/configured_catalog.json ``` -## Testing +### Running our CI test suite + You can run our full test suite locally using [`airbyte-ci`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md): + ```bash airbyte-ci connectors --name=source-recurly test ``` ### Customizing acceptance Tests -Customize `acceptance-test-config.yml` file to configure tests. See [Connector Acceptance Tests](https://docs.airbyte.com/connector-development/testing-connectors/connector-acceptance-tests-reference) for more information. -If your connector requires to create or destroy resources for use during acceptance tests create fixtures for it and place them inside integration_tests/acceptance.py. -## Dependency Management -All of your dependencies should go in `setup.py`, NOT `requirements.txt`. The requirements file is only used to connect internal Airbyte dependencies in the monorepo for local development. -We split dependencies between two groups, dependencies that are: -* required for your connector to work need to go to `MAIN_REQUIREMENTS` list. -* required for the testing need to go to `TEST_REQUIREMENTS` list +Customize the `acceptance-test-config.yml` file to configure acceptance tests. See our [Connector Acceptance Tests reference](https://docs.airbyte.com/connector-development/testing-connectors/connector-acceptance-tests-reference) for more information. +If your connector requires you to create or destroy resources for use during acceptance tests create fixtures for it and place them inside integration_tests/acceptance.py. + +### Dependency Management + +All of your dependencies should be managed via Poetry. To add a new dependency, run: + +```bash +poetry add +``` + +Please commit the changes to the `pyproject.toml` and `poetry.lock` files. + +## Publishing a new version of the connector -### Publishing a new version of the connector You've checked out the repo, implemented a million dollar feature, and you're ready to share your changes with the world. Now what? + 1. Make sure your changes are passing our test suite: `airbyte-ci connectors --name=source-recurly test` -2. Bump the connector version in `metadata.yaml`: increment the `dockerImageTag` value. Please follow [semantic versioning for connectors](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#semantic-versioning-for-connectors). +2. Bump the connector version listed as `dockerImageTag` in `metadata.yaml`. Please follow [semantic versioning for connectors](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#semantic-versioning-for-connectors). 3. Make sure the `metadata.yaml` content is up to date. 4. Make the connector documentation and its changelog is up to date (`docs/integrations/sources/recurly.md`). 5. Create a Pull Request: use [our PR naming conventions](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#pull-request-title-convention). 6. Pat yourself on the back for being an awesome contributor. 7. Someone from Airbyte will take a look at your PR and iterate with you to merge it into master. - +8. Once your PR is merged, the new version of the connector will be automatically published to Docker Hub and our connector registry. diff --git a/airbyte-integrations/connectors/source-recurly/acceptance-test-config.yml b/airbyte-integrations/connectors/source-recurly/acceptance-test-config.yml index 863cbc656d27..c1e9dfe6ee73 100644 --- a/airbyte-integrations/connectors/source-recurly/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-recurly/acceptance-test-config.yml @@ -1,35 +1,40 @@ # See [Connector Acceptance Tests](https://docs.airbyte.com/connector-development/testing-connectors/connector-acceptance-tests-reference) # for more information about how to configure these tests connector_image: airbyte/source-recurly:dev -tests: +acceptance_tests: spec: - - spec_path: "source_recurly/spec.json" + tests: + - spec_path: "source_recurly/spec.json" connection: - - config_path: "secrets/config.json" - status: "succeed" - - config_path: "integration_tests/invalid_config.json" - status: "failed" + tests: + - config_path: "secrets/config.json" + status: "succeed" + - config_path: "integration_tests/invalid_config.json" + status: "failed" discovery: - - config_path: "secrets/config.json" + tests: + - config_path: "secrets/config.json" basic_read: - - config_path: "secrets/config.json" - configured_catalog_path: "integration_tests/configured_catalog.json" - empty_streams: - [ - "account_coupon_redemptions", - "account_notes", - "add_ons", - "billing_infos", - "credit_payments", - "line_items", - "shipping_methods", - "unique_coupons", - "export_dates", - ] + tests: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" + empty_streams: + - name: "add_ons" + bypass_reason: "Cannot seed this stream with free sandbox account" + - name: "billing_infos" + bypass_reason: "Cannot seed this stream with free sandbox account" + - name: "credit_payments" + bypass_reason: "Cannot seed this stream with free sandbox account" + - name: "shipping_methods" + bypass_reason: "Cannot seed this stream with free sandbox account" full_refresh: - - config_path: "secrets/config.json" - configured_catalog_path: "integration_tests/configured_catalog.json" + tests: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" incremental: - - config_path: "secrets/config.json" - configured_catalog_path: "integration_tests/configured_catalog.json" - future_state_path: "integration_tests/future_state.json" + tests: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" + future_state: + future_state_path: "integration_tests/future_state.json" + skip_comprehensive_incremental_tests: true diff --git a/airbyte-integrations/connectors/source-recurly/integration_tests/future_state.json b/airbyte-integrations/connectors/source-recurly/integration_tests/future_state.json index 0cc9399e6fae..1c9442f7c6d3 100644 --- a/airbyte-integrations/connectors/source-recurly/integration_tests/future_state.json +++ b/airbyte-integrations/connectors/source-recurly/integration_tests/future_state.json @@ -1,50 +1,114 @@ -{ - "accounts": { - "updated_at": "2022-07-19T22:21:37Z" +[ + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "accounts" } + } }, - "account_coupon_redemptions": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "account_coupon_redemptions" } + } }, - "account_notes": { - "created_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "created_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "account_notes" } + } }, - "add_ons": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "add_ons" } + } }, - "billing_infos": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "billing_infos" } + } }, - "coupons": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "coupons" } + } }, - "credit_payments": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "credit_payments" } + } }, - "invoices": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "invoices" } + } }, - "line_items": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "line_items" } + } }, - "measured_units": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "measured_units" } + } }, - "plans": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "plans" } + } }, - "shipping_addresses": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "shipping_addresses" } + } }, - "shipping_methods": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "shipping_methods" } + } }, - "subscriptions": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "subscriptions" } + } }, - "transactions": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "transactions" } + } }, - "unique_coupons": { - "updated_at": "2022-07-19T22:21:37Z" + { + "type": "STREAM", + "stream": { + "stream_state": { "updated_at": "2036-07-19T22:21:37Z" }, + "stream_descriptor": { "name": "unique_coupons" } + } } -} +] diff --git a/airbyte-integrations/connectors/source-recurly/metadata.yaml b/airbyte-integrations/connectors/source-recurly/metadata.yaml index 21e36b99bf4d..0a8afd004e8d 100644 --- a/airbyte-integrations/connectors/source-recurly/metadata.yaml +++ b/airbyte-integrations/connectors/source-recurly/metadata.yaml @@ -2,26 +2,28 @@ data: ab_internal: ql: 200 sl: 100 + connectorBuildOptions: + baseImage: docker.io/airbyte/python-connector-base:1.2.0@sha256:c22a9d97464b69d6ef01898edf3f8612dc11614f05a84984451dde195f337db9 connectorSubtype: api connectorType: source definitionId: cd42861b-01fc-4658-a8ab-5d11d0510f01 - dockerImageTag: 0.4.1 + dockerImageTag: 0.5.0 dockerRepository: airbyte/source-recurly documentationUrl: https://docs.airbyte.com/integrations/sources/recurly githubIssueLabel: source-recurly icon: recurly.svg license: MIT name: Recurly + registries: + cloud: + enabled: true + oss: + enabled: true + releaseStage: alpha remoteRegistries: pypi: enabled: true packageName: airbyte-source-recurly - registries: # Removed from registries due to LEGACY STATE - cloud: - enabled: false - oss: - enabled: false - releaseStage: alpha supportLevel: community tags: - language:python diff --git a/airbyte-integrations/connectors/source-recurly/poetry.lock b/airbyte-integrations/connectors/source-recurly/poetry.lock new file mode 100644 index 000000000000..144b7f527169 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/poetry.lock @@ -0,0 +1,1045 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "airbyte-cdk" +version = "0.67.0" +description = "A framework for writing Airbyte Connectors." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte-cdk-0.67.0.tar.gz", hash = "sha256:cbbff1b3895c89313764a721870bb293a396c74bad8dd6e5c36a0c3b0a2f6a10"}, + {file = "airbyte_cdk-0.67.0-py3-none-any.whl", hash = "sha256:2082c859536a2450c03b89dba1bbdab21bad314fbf5ef6d2e86fefc4ba935373"}, +] + +[package.dependencies] +airbyte-protocol-models = "0.5.1" +backoff = "*" +cachetools = "*" +Deprecated = ">=1.2,<2.0" +dpath = ">=2.0.1,<2.1.0" +genson = "1.2.2" +isodate = ">=0.6.1,<0.7.0" +Jinja2 = ">=3.1.2,<3.2.0" +jsonref = ">=0.2,<1.0" +jsonschema = ">=3.2.0,<3.3.0" +pendulum = "<3.0.0" +pydantic = ">=1.10.8,<2.0.0" +pyrate-limiter = ">=3.1.0,<3.2.0" +python-dateutil = "*" +PyYAML = ">=6.0.1" +requests = "*" +requests-cache = "*" +wcmatch = "8.4" + +[package.extras] +dev = ["avro (>=1.11.2,<1.12.0)", "cohere (==4.21)", "fastavro (>=1.8.0,<1.9.0)", "freezegun", "langchain (==0.0.271)", "markdown", "mypy", "openai[embeddings] (==0.27.9)", "pandas (==2.0.3)", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "pytest", "pytest-cov", "pytest-httpserver", "pytest-mock", "requests-mock", "tiktoken (==0.4.0)", "unstructured (==0.10.27)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] +file-based = ["avro (>=1.11.2,<1.12.0)", "fastavro (>=1.8.0,<1.9.0)", "markdown", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "unstructured (==0.10.27)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] +sphinx-docs = ["Sphinx (>=4.2,<5.0)", "sphinx-rtd-theme (>=1.0,<2.0)"] +vector-db-based = ["cohere (==4.21)", "langchain (==0.0.271)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.4.0)"] + +[[package]] +name = "airbyte-protocol-models" +version = "0.5.1" +description = "Declares the Airbyte Protocol." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte_protocol_models-0.5.1-py3-none-any.whl", hash = "sha256:dfe84e130e51ce2ae81a06d5aa36f6c5ce3152b9e36e6f0195fad6c3dab0927e"}, + {file = "airbyte_protocol_models-0.5.1.tar.gz", hash = "sha256:7c8b16c7c1c7956b1996052e40585a3a93b1e44cb509c4e97c1ee4fe507ea086"}, +] + +[package.dependencies] +pydantic = ">=1.9.2,<2.0.0" + +[[package]] +name = "atomicwrites" +version = "1.4.1" +description = "Atomic file writes." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, +] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bracex" +version = "2.4" +description = "Bash style brace expander." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, + {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, +] + +[[package]] +name = "cachetools" +version = "5.3.2" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, +] + +[[package]] +name = "cattrs" +version = "23.2.3" +description = "Composable complex class support for attrs and dataclasses." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cattrs-23.2.3-py3-none-any.whl", hash = "sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"}, + {file = "cattrs-23.2.3.tar.gz", hash = "sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f"}, +] + +[package.dependencies] +attrs = ">=23.1.0" +exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_version < \"3.11\""} + +[package.extras] +bson = ["pymongo (>=4.4.0)"] +cbor2 = ["cbor2 (>=5.4.6)"] +msgpack = ["msgpack (>=1.0.5)"] +orjson = ["orjson (>=3.9.2)"] +pyyaml = ["pyyaml (>=6.0)"] +tomlkit = ["tomlkit (>=0.11.8)"] +ujson = ["ujson (>=5.7.0)"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + +[[package]] +name = "dpath" +version = "2.0.8" +description = "Filesystem-like pathing and searching for dictionaries" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"}, + {file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "genson" +version = "1.2.2" +description = "GenSON is a powerful, user-friendly JSON Schema generator." +optional = false +python-versions = "*" +files = [ + {file = "genson-1.2.2.tar.gz", hash = "sha256:8caf69aa10af7aee0e1a1351d1d06801f4696e005f06cedef438635384346a16"}, +] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +optional = false +python-versions = "*" +files = [ + {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, + {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonref" +version = "0.3.0" +description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." +optional = false +python-versions = ">=3.3,<4.0" +files = [ + {file = "jsonref-0.3.0-py3-none-any.whl", hash = "sha256:9480ad1b500f7e795daeb0ef29f9c55ae3a9ab38fb8d6659b6f4868acb5a5bc8"}, + {file = "jsonref-0.3.0.tar.gz", hash = "sha256:68b330c6815dc0d490dbb3d65ccda265ddde9f7856fd2f3322f971d456ea7549"}, +] + +[[package]] +name = "jsonschema" +version = "3.2.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = "*" +files = [ + {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, + {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0" +setuptools = "*" +six = ">=1.11.0" + +[package.extras] +format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] +format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pendulum" +version = "2.1.2" +description = "Python datetimes made easy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, + {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, + {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"}, + {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"}, + {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"}, + {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"}, + {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"}, + {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"}, + {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"}, + {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"}, + {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"}, +] + +[package.dependencies] +python-dateutil = ">=2.6,<3.0" +pytzdata = ">=2020.1" + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] + +[[package]] +name = "pydantic" +version = "1.10.14" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, + {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, + {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, + {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, + {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, + {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, + {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, + {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, + {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, + {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pyrate-limiter" +version = "3.1.1" +description = "Python Rate-Limiter using Leaky-Bucket Algorithm" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "pyrate_limiter-3.1.1-py3-none-any.whl", hash = "sha256:c51906f1d51d56dc992ff6c26e8300e32151bc6cfa3e6559792e31971dfd4e2b"}, + {file = "pyrate_limiter-3.1.1.tar.gz", hash = "sha256:2f57eda712687e6eccddf6afe8f8a15b409b97ed675fe64a626058f12863b7b7"}, +] + +[package.extras] +all = ["filelock (>=3.0)", "redis (>=5.0.0,<6.0.0)"] +docs = ["furo (>=2022.3.4,<2023.0.0)", "myst-parser (>=0.17)", "sphinx (>=4.3.0,<5.0.0)", "sphinx-autodoc-typehints (>=1.17,<2.0)", "sphinx-copybutton (>=0.5)", "sphinxcontrib-apidoc (>=0.3,<0.4)"] + +[[package]] +name = "pyrsistent" +version = "0.20.0" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, + {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, + {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, + {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, + {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, + {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, + {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, +] + +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-mock" +version = "3.12.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, + {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, +] + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytzdata" +version = "2020.1" +description = "The Olson timezone database for Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, + {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "recurly" +version = "4.10.0" +description = "Recurly v4" +optional = false +python-versions = "*" +files = [ + {file = "recurly-4.10.0-py3-none-any.whl", hash = "sha256:b8e3b1ec58f7b1e1b91286f2db864f6ba4053837ad920d0c2868508020442aaf"}, + {file = "recurly-4.10.0.tar.gz", hash = "sha256:a8dddab76bb38f76a715644448f45499227bfd00529ef33f7945b3bcc5a8f3a2"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-cache" +version = "1.2.0" +description = "A persistent cache for python requests" +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"}, + {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"}, +] + +[package.dependencies] +attrs = ">=21.2" +cattrs = ">=22.2" +platformdirs = ">=2.5" +requests = ">=2.22" +url-normalize = ">=1.4" +urllib3 = ">=1.25.5" + +[package.extras] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] +bson = ["bson (>=0.5)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] +dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] +json = ["ujson (>=5.4)"] +mongodb = ["pymongo (>=3)"] +redis = ["redis (>=3)"] +security = ["itsdangerous (>=2.0)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "requests-mock" +version = "1.11.0" +description = "Mock out responses from the requests package" +optional = false +python-versions = "*" +files = [ + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, +] + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] + +[[package]] +name = "setuptools" +version = "69.1.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, + {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] + +[[package]] +name = "url-normalize" +version = "1.4.3" +description = "URL normalization for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, + {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wcmatch" +version = "8.4" +description = "Wildcard/glob file name matcher." +optional = false +python-versions = ">=3.7" +files = [ + {file = "wcmatch-8.4-py3-none-any.whl", hash = "sha256:dc7351e5a7f8bbf4c6828d51ad20c1770113f5f3fd3dfe2a03cfde2a63f03f98"}, + {file = "wcmatch-8.4.tar.gz", hash = "sha256:ba4fc5558f8946bf1ffc7034b05b814d825d694112499c86035e0e4d398b6a67"}, +] + +[package.dependencies] +bracex = ">=2.1.1" + +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9,<3.12" +content-hash = "d85022c0f25e080bc6664f5dd4f866b1ef1dbe94bf07b5ad77a8eb4d45987798" diff --git a/airbyte-integrations/connectors/source-recurly/pyproject.toml b/airbyte-integrations/connectors/source-recurly/pyproject.toml new file mode 100644 index 000000000000..7e1569523ee2 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/pyproject.toml @@ -0,0 +1,29 @@ +[build-system] +requires = [ "poetry-core>=1.0.0",] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +version = "0.5.0" +name = "source-recurly" +description = "Source implementation for Recurly." +authors = [ "Airbyte ",] +license = "MIT" +readme = "README.md" +documentation = "https://docs.airbyte.com/integrations/sources/recurly" +homepage = "https://airbyte.com" +repository = "https://github.com/airbytehq/airbyte" +[[tool.poetry.packages]] +include = "source_recurly" + +[tool.poetry.dependencies] +python = "^3.9,<3.12" +airbyte-cdk = "^0.67.0" +recurly = "==4.10.0" + +[tool.poetry.scripts] +source-recurly = "source_recurly.run:run" + +[tool.poetry.group.dev.dependencies] +requests-mock = "^1.9.3" +pytest-mock = "^3.6.1" +pytest = "^6.1" diff --git a/airbyte-integrations/connectors/source-recurly/requirements.txt b/airbyte-integrations/connectors/source-recurly/requirements.txt deleted file mode 100644 index 7b9114ed5867..000000000000 --- a/airbyte-integrations/connectors/source-recurly/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# This file is autogenerated -- only edit if you know what you are doing. Use setup.py for declaring dependencies. --e . diff --git a/airbyte-integrations/connectors/source-recurly/setup.py b/airbyte-integrations/connectors/source-recurly/setup.py deleted file mode 100644 index 1d1cce5a7cd7..000000000000 --- a/airbyte-integrations/connectors/source-recurly/setup.py +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from setuptools import find_packages, setup - -MAIN_REQUIREMENTS = ["airbyte-cdk~=0.1", "recurly==4.10.0", "requests"] - -TEST_REQUIREMENTS = [ - "requests-mock~=1.9.3", - "pytest~=6.1", - "pytest-mock~=3.6.1", -] - -setup( - entry_points={ - "console_scripts": [ - "source-recurly=source_recurly.run:run", - ], - }, - name="source_recurly", - description="Source implementation for Recurly.", - author="Airbyte", - author_email="contact@airbyte.io", - packages=find_packages(), - install_requires=MAIN_REQUIREMENTS, - package_data={ - "": [ - # Include yaml files in the package (if any) - "*.yml", - "*.yaml", - # Include all json files in the package, up to 4 levels deep - "*.json", - "*/*.json", - "*/*/*.json", - "*/*/*/*.json", - "*/*/*/*/*.json", - ] - }, - extras_require={ - "tests": TEST_REQUIREMENTS, - }, -) diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_coupon_redemptions.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_coupon_redemptions.json index f49ddee10ee6..d9e894d584d3 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_coupon_redemptions.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_coupon_redemptions.json @@ -6,35 +6,18 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "account": { - "type": "object", - "properties": { - "id": { - "type": ["null", "string"], - "maxLength": 13 - }, - "code": { - "type": ["null", "string"], - "maxLength": 50 - } - } + "$ref": "account_details.json" }, "subscription_id": { "type": ["null", "string"], "maxLength": 13 }, "coupon": { - "type": "object", - "properties": { - "id": { - "type": ["null", "string"], - "maxLength": 13 - }, - "code": { - "type": ["null", "string"], - "maxLength": 256 - } - } + "$ref": "coupons.json" }, "state": { "type": ["null", "string"], diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_notes.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_notes.json index 830233d4d39e..ee68e82c8973 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_notes.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/account_notes.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": { @@ -7,19 +7,15 @@ "maxLength": 13, "readOnly": true }, + "object": { + "type": ["null", "string"] + }, "account_id": { "type": "string", "maxLength": 13 }, "user": { - "type": "object", - "properties": { - "id": { - "type": "string", - "readOnly": true, - "maxLength": 13 - } - } + "$ref": "users.json" }, "message": { "type": ["null", "string"], diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/accounts.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/accounts.json index 013509268cf4..c9f1c5b84953 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/accounts.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/accounts.json @@ -6,6 +6,12 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, + "hosted_login_token": { + "type": ["null", "string"] + }, "code": { "type": ["null", "string"], "maxLength": 256 @@ -101,11 +107,18 @@ "title": "Country", "description": "Country, 2-letter ISO 3166-1 alpha-2 code.", "maxLength": 2 + }, + "geo_code": { + "type": ["null", "string"] } } }, "custom_fields": { - "type": ["null", "array"] + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true + } }, "has_live_subscription": { "type": ["null", "boolean"] @@ -140,6 +153,30 @@ "deleted_at": { "type": ["null", "string"], "format": "date-time" + }, + "billing_info": { + "$ref": "billing_infos.json" + }, + "external_accounts": { + "type": ["null", "array"], + "items": { + "$ref": "external_accounts.json" + } + }, + "invoice_template_id": { + "type": ["null", "string"] + }, + "override_business_entity_id": { + "type": ["null", "string"] + }, + "preferred_time_zone": { + "type": ["null", "string"] + }, + "shipping_addresses": { + "type": ["null", "array"], + "items": { + "$ref": "shipping_addresses.json" + } } } } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/billing_infos.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/billing_infos.json index f2cdc6f0c8bd..5dd179d84f39 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/billing_infos.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/billing_infos.json @@ -1,196 +1,3 @@ { - "$schema": "http://json-schema.org/schema#", - "type": "object", - "properties": { - "id": { - "type": "string", - "maxLength": 13, - "readOnly": true - }, - "account_id": { - "type": "string", - "maxLength": 13, - "readOnly": true - }, - "first_name": { - "type": "string", - "maxLength": 50 - }, - "last_name": { - "type": "string", - "maxLength": 50 - }, - "company": { - "type": "string", - "maxLength": 100 - }, - "address": { - "type": "object", - "properties": { - "phone": { - "type": "string", - "title": "Phone number", - "maxLength": 256 - }, - "street1": { - "type": "string", - "title": "Street 1", - "maxLength": 256 - }, - "street2": { - "type": "string", - "title": "Street 2", - "maxLength": 256 - }, - "city": { - "type": "string", - "title": "City", - "maxLength": 256 - }, - "region": { - "type": "string", - "title": "State/Province", - "description": "State or province.", - "maxLength": 256 - }, - "postal_code": { - "type": "string", - "title": "Zip/Postal code", - "description": "Zip or postal code.", - "maxLength": 256 - }, - "country": { - "type": "string", - "title": "Country", - "description": "Country, 2-letter ISO 3166-1 alpha-2 code.", - "maxLength": 2 - } - } - }, - "vat_number": { - "type": "string", - "description": "Customer's VAT number (to avoid having the VAT applied). This is only used for automatically collected invoices.", - "maxLength": 20 - }, - "valid": { - "type": "boolean", - "readOnly": true - }, - "payment_method": { - "type": "object", - "properties": { - "card_type": { - "description": "Visa, MasterCard, American Express, Discover, JCB, etc.", - "type": "string", - "maxLength": 256 - }, - "first_six": { - "type": "string", - "description": "Credit card number's first six digits.", - "maxLength": 6 - }, - "last_four": { - "type": "string", - "description": "Credit card number's last four digits. Will refer to bank account if payment method is ACH.", - "maxLength": 4 - }, - "last_two": { - "type": "string", - "description": "The IBAN bank account's last two digits.", - "maxLength": 2 - }, - "exp_month": { - "type": "integer", - "description": "Expiration month.", - "maxLength": 2 - }, - "exp_year": { - "type": "integer", - "description": "Expiration year.", - "maxLength": 4 - }, - "gateway_token": { - "type": "string", - "description": "A token used in place of a credit card in order to perform transactions.", - "maxLength": 50 - }, - "cc_bin_country": { - "type": "string", - "description": "The 2-letter ISO 3166-1 alpha-2 country code associated with the credit card BIN, if known by Recurly. Available on the BillingInfo object only. Available when the BIN country lookup feature is enabled.", - "maxLength": 256 - }, - "gateway_code": { - "type": "string", - "description": "An identifier for a specific payment gateway.", - "maxLength": 13 - }, - "billing_agreement_id": { - "type": "string", - "description": "Billing Agreement identifier. Only present for Amazon or Paypal payment methods.", - "maxLength": 256 - }, - "name_on_account": { - "type": "string", - "description": "The name associated with the bank account.", - "maxLength": 256 - }, - "account_type": { - "description": "The bank account type. Only present for ACH payment methods.", - "type": "string", - "maxLength": 256 - }, - "routing_number": { - "type": "string", - "description": "The bank account's routing number. Only present for ACH payment methods.", - "maxLength": 256 - }, - "routing_number_bank": { - "type": "string", - "description": "The bank name of this routing number.", - "maxLength": 256 - } - } - }, - "fraud": { - "type": "object", - "title": "Fraud information", - "description": "Most recent fraud result.", - "readOnly": true, - "properties": { - "score": { - "type": "integer", - "title": "Kount score" - }, - "decision": { - "title": "Kount decision", - "maxLength": 10, - "type": "string" - }, - "risk_rules_triggered": { - "type": "object", - "title": "Kount rules" - } - } - }, - "primary_payment_method": { - "type": "boolean", - "description": "The `primary_payment_method` field is used to indicate the primary billing info on the account. The first billing info created on an account will always become primary. This payment method will be used" - }, - "backup_payment_method": { - "type": "boolean", - "description": "The `backup_payment_method` field is used to indicate a billing info as a backup on the account that will be tried if the initial billing info used for an invoice is declined." - }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "When the billing information was created.", - "readOnly": true - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "When the billing information was last changed.", - "readOnly": true - } - } + "$ref": "billing_infos.json" } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/coupons.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/coupons.json index 9fc95eaf9416..9c262d6773c3 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/coupons.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/coupons.json @@ -1,188 +1,3 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "id": { - "type": ["null", "string"], - "maxLength": 13 - }, - "code": { - "type": ["null", "string"], - "maxLength": 256 - }, - "name": { - "type": ["null", "string"], - "maxLength": 256 - }, - "state": { - "type": ["null", "string"], - "maxLength": 256 - }, - "max_redemptions": { - "type": ["null", "number"] - }, - "max_redemptions_per_account": { - "type": ["null", "number"] - }, - "unique_coupon_codes_count": { - "type": ["null", "number"] - }, - "unique_code_template": { - "type": ["null", "string"], - "maxLength": 256 - }, - "duration": { - "type": ["null", "string"], - "maxLength": 256 - }, - "temporal_amount": { - "type": ["null", "number"] - }, - "temporal_unit": { - "type": ["null", "string"], - "maxLength": 256 - }, - "free_trial_unit": { - "type": ["null", "string"], - "maxLength": 256 - }, - "free_trial_amount": { - "type": ["null", "number"] - }, - "applies_to_all_plans": { - "type": ["null", "boolean"] - }, - "applies_to_all_items": { - "type": ["null", "boolean"] - }, - "applies_to_non_plan_charges": { - "type": ["null", "boolean"] - }, - "plans": { - "type": ["null", "array"], - "title": "Plans", - "description": "A list of plans for which this coupon applies. This will be `null` if `applies_to_all_plans=true`.", - "items": { - "type": "object", - "title": "Plan mini details", - "description": "Just the important parts.", - "properties": { - "id": { - "type": "string", - "title": "Plan ID", - "maxLength": 13, - "readOnly": true - }, - "code": { - "type": "string", - "title": "Plan code", - "description": "Unique code to identify the plan. This is used in Hosted Payment Page URLs and in the invoice exports.", - "maxLength": 13 - } - } - } - }, - "items": { - "type": ["null", "array"], - "title": "Items", - "description": "A list of items for which this coupon applies. This will be\n`null` if `applies_to_all_items=true`.\n", - "items": { - "type": ["null", "object"], - "title": "Item mini details", - "description": "Just the important parts.", - "properties": { - "id": { - "type": "string", - "title": "Item ID", - "maxLength": 13, - "readOnly": true - } - } - } - }, - "redemption_resource": { - "type": ["null", "string"], - "maxLength": 256 - }, - "discount": { - "type": ["null", "object"], - "description": "Details of the discount a coupon applies. Will contain a `type`\nproperty and one of the following properties: `percent`, `fixed`, `trial`.\n", - "properties": { - "type": { - "type": "string", - "maxLength": 256 - }, - "percent": { - "description": "This is only present when `type=percent`.", - "type": "integer" - }, - "currencies": { - "type": "array", - "description": "This is only present when `type=fixed`.", - "items": { - "type": ["null", "object"], - "properties": { - "currency": { - "type": "string", - "title": "Currency", - "description": "3-letter ISO 4217 currency code.", - "maxLength": 3 - }, - "amount": { - "type": "number", - "format": "float", - "title": "Discount Amount", - "description": "Value of the fixed discount that this coupon applies." - } - } - } - }, - "trial": { - "type": "object", - "description": "This is only present when `type=free_trial`.", - "properties": { - "unit": { - "title": "Trial unit", - "description": "Temporal unit of the free trial", - "type": "string", - "maxLength": 256 - }, - "length": { - "type": "integer", - "title": "Trial length", - "description": "Trial length measured in the units specified by the sibling `unit` property" - } - } - } - } - }, - "coupon_type": { - "type": ["null", "string"], - "maxLength": 256 - }, - "hosted_page_description": { - "type": ["null", "string"], - "maxLength": 1024 - }, - "invoice_description": { - "type": ["null", "string"], - "maxLength": 1024 - }, - "redeem_by": { - "type": ["null", "string"], - "maxLength": 256 - }, - "created_at": { - "type": ["null", "string"], - "format": "date-time" - }, - "updated_at": { - "type": ["null", "string"], - "format": "date-time" - }, - "expired_at": { - "type": ["null", "string"], - "format": "date-time" - } - } + "$ref": "coupons.json" } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/invoices.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/invoices.json index 64db09629b59..6e5f4732e079 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/invoices.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/invoices.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": { @@ -8,6 +8,12 @@ "readOnly": true, "maxLength": 13 }, + "uuid": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, "type": { "title": "Invoice type", "description": "Invoices are either charge, credit, or legacy invoices.", @@ -26,20 +32,7 @@ "maxLength": 256 }, "account": { - "type": "object", - "title": "Account mini details", - "properties": { - "id": { - "type": ["null", "string"], - "maxLength": 13, - "readOnly": true - }, - "code": { - "type": ["null", "string"], - "description": "The unique identifier of the account.", - "maxLength": 50 - } - } + "$ref": "account_details.json" }, "billing_info_id": { "type": ["null", "string"], @@ -264,6 +257,9 @@ } } }, + "used_tax_service": { + "type": ["null", "boolean"] + }, "vat_number": { "type": ["null", "string"], "title": "VAT number", @@ -292,23 +288,12 @@ "type": ["null", "array"], "title": "Line Items", "items": { - "type": ["null", "object"], - "title": "Line item", - "properties": { - "id": { - "type": "string", - "title": "Line item ID", - "maxLength": 13 - }, - "uuid": { - "type": "string", - "title": "UUID", - "description": "The UUID is useful for matching data with the CSV exports and building URLs into Recurly's UI.", - "maxLength": 32 - } - } + "$ref": "line_items.json" } }, + "has_more_line_items": { + "type": ["null", "boolean"] + }, "transactions": { "type": ["null", "array"], "title": "Transactions", @@ -378,6 +363,15 @@ "title": "Dunning Campaign ID", "description": "Unique ID to identify the dunning campaign used when dunning the invoice. Available when the Dunning Campaigns feature is enabled. For sites without multiple dunning campaigns enabled, this will always be the default dunning campaign.", "maxLength": 256 + }, + "dunning_events_sent": { + "type": ["null", "integer"] + }, + "final_dunning_event": { + "type": ["null", "boolean"] + }, + "business_entity_id": { + "type": ["null", "string"] } } } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/line_items.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/line_items.json index c981890d97ab..85370cc75850 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/line_items.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/line_items.json @@ -1,270 +1,3 @@ { - "$schema": "http://json-schema.org/schema#", - "type": "object", - "title": "Line item", - "properties": { - "id": { - "type": "string", - "title": "Line item ID", - "maxLength": 13 - }, - "uuid": { - "type": "string", - "title": "UUID", - "description": "The UUID is useful for matching data with the CSV exports and building URLs into Recurly's UI.", - "maxLength": 32 - }, - "type": { - "type": "string", - "title": "Line item type", - "description": "Charges are positive line items that debit the account. Credits are negative line items that credit the account.", - "maxLength": 256 - }, - "item_code": { - "type": ["null", "string"], - "title": "Item Code", - "description": "Unique code to identify an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", - "maxLength": 50 - }, - "item_id": { - "type": ["null", "string"], - "title": "Item ID", - "description": "System-generated unique identifier for an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", - "maxLength": 13 - }, - "external_sku": { - "type": ["null", "string"], - "title": "External SKU", - "description": "Optional Stock Keeping Unit assigned to an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", - "maxLength": 50 - }, - "revenue_schedule_type": { - "type": ["null", "string"], - "title": "Revenue schedule type", - "maxLength": 256 - }, - "state": { - "type": "string", - "title": "Current state of the line item", - "description": "Pending line items are charges or credits on an account that have not been applied to an invoice yet. Invoiced line items will always have an `invoice_id` value.", - "maxLength": 256 - }, - "legacy_category": { - "type": ["null", "string"], - "title": "Legacy category", - "description": "Category to describe the role of a line item on a legacy invoice:\n- \"charges\" refers to charges being billed for on this invoice.\n- \"credits\" refers to refund or proration credits. This portion of the invoice can be considered a credit memo.\n- \"applied_credits\" refers to previous credits applied to this invoice. See their original_line_item_id to determine where the credit first originated.\n- \"carryforwards\" can be ignored. They exist to consume any remaining credit balance. A new credit with the same amount will be created and placed back on the account.\n" - }, - "bill_for_account_id": { - "type": "string", - "title": "Bill For Account ID", - "maxLength": 13, - "description": "The UUID of the account responsible for originating the line item." - }, - "subscription_id": { - "type": ["null", "string"], - "title": "Subscription ID", - "description": "If the line item is a charge or credit for a subscription, this is its ID.", - "maxLength": 13 - }, - "plan_id": { - "type": ["null", "string"], - "title": "Plan ID", - "description": "If the line item is a charge or credit for a plan or add-on, this is the plan's ID.", - "maxLength": 13 - }, - "plan_code": { - "type": ["null", "string"], - "title": "Plan code", - "description": "If the line item is a charge or credit for a plan or add-on, this is the plan's code.", - "maxLength": 50 - }, - "add_on_id": { - "type": ["null", "string"], - "title": "Add-on ID", - "description": "If the line item is a charge or credit for an add-on this is its ID.", - "maxLength": 13 - }, - "add_on_code": { - "type": ["null", "string"], - "title": "Add-on code", - "description": "If the line item is a charge or credit for an add-on, this is its code.", - "maxLength": 50 - }, - "invoice_id": { - "type": ["null", "string"], - "title": "Invoice ID", - "description": "Once the line item has been invoiced this will be the invoice's ID.", - "maxLength": 13 - }, - "invoice_number": { - "type": ["null", "string"], - "title": "Invoice number", - "description": "Once the line item has been invoiced this will be the invoice's number. If VAT taxation and the Country Invoice Sequencing feature are enabled, invoices will have country-specific invoice numbers for invoices billed to EU countries (ex: FR1001). Non-EU invoices will continue to use the site-level invoice number sequence.", - "maxLength": 256 - }, - "previous_line_item_id": { - "type": ["null", "string"], - "title": "Previous line item ID", - "description": "Will only have a value if the line item is a credit created from a previous credit, or if the credit was created from a charge refund.", - "maxLength": 13 - }, - "original_line_item_invoice_id": { - "type": ["null", "string"], - "title": "Original line item's invoice ID", - "description": "The invoice where the credit originated. Will only have a value if the line item is a credit created from a previous credit, or if the credit was created from a charge refund.", - "maxLength": 13 - }, - "origin": { - "type": "string", - "title": "Origin of line item", - "description": "A credit created from an original charge will have the value of the charge's origin.", - "maxLength": 256 - }, - "accounting_code": { - "type": "string", - "title": "Accounting code", - "description": "Internal accounting code to help you reconcile your revenue to the correct ledger. Line items created as part of a subscription invoice will use the plan or add-on's accounting code, otherwise the value will only be present if you define an accounting code when creating the line item.", - "maxLength": 20 - }, - "product_code": { - "type": "string", - "title": "Product code", - "description": "For plan-related line items this will be the plan's code, for add-on related line items it will be the add-on's code. For item-related line items it will be the item's `external_sku`.", - "maxLength": 50 - }, - "credit_reason_code": { - "type": ["null", "string"], - "title": "Credit reason code", - "description": "The reason the credit was given when line item is `type=credit`.", - "default": "general", - "maxLength": 256 - }, - "currency": { - "type": "string", - "title": "Currency", - "description": "3-letter ISO 4217 currency code.", - "maxLength": 3 - }, - "amount": { - "type": "number", - "format": "float", - "title": "Total after discounts and taxes", - "description": "`(quantity * unit_amount) - (discount + tax)`" - }, - "description": { - "type": "string", - "title": "Description", - "description": "Description that appears on the invoice. For subscription related items this will be filled in automatically.", - "maxLength": 255 - }, - "quantity": { - "type": "integer", - "title": "Quantity", - "description": "This number will be multiplied by the unit amount to compute the subtotal before any discounts or taxes.", - "default": 1 - }, - "unit_amount": { - "type": "number", - "format": "float", - "title": "Unit amount", - "description": "Positive amount for a charge, negative amount for a credit." - }, - "unit_amount_decimal": { - "type": ["null", "string"], - "title": "Unit amount decimal", - "description": "Positive amount for a charge, negative amount for a credit." - }, - "subtotal": { - "type": "number", - "format": "float", - "title": "Total before discounts and taxes", - "description": "`quantity * unit_amount`" - }, - "discount": { - "type": ["null", "number"], - "format": "float", - "title": "Discount", - "description": "The discount applied to the line item." - }, - "tax": { - "type": ["null", "number"], - "format": "float", - "title": "Tax", - "description": "The tax amount for the line item." - }, - "taxable": { - "type": "boolean", - "title": "Taxable?", - "description": "`true` if the line item is taxable, `false` if it is not." - }, - "tax_exempt": { - "type": "boolean", - "title": "Tax exempt?", - "description": "`true` exempts tax on charges, `false` applies tax on charges. If not defined, then defaults to the Plan and Site settings. This attribute does not work for credits (negative line items). Credits are always applied post-tax. Pre-tax discounts should use the Coupons feature." - }, - "tax_code": { - "type": ["null", "string"], - "title": "Tax code", - "description": "Used by Avalara, Vertex, and Recurly\u2019s EU VAT tax feature. The tax code values are specific to each tax system. If you are using Recurly\u2019s EU VAT feature you can use `unknown`, `physical`, or `digital`.", - "maxLength": 50 - }, - "proration_rate": { - "type": ["null", "number"], - "format": "float", - "title": "Proration rate", - "description": "When a line item has been prorated, this is the rate of the proration. Proration rates were made available for line items created after March 30, 2017. For line items created prior to that date, the proration rate will be `null`, even if the line item was prorated.", - "minimum": 0, - "maximum": 1 - }, - "refund": { - "type": "boolean", - "title": "Refund?" - }, - "refunded_quantity": { - "type": ["null", "integer"], - "title": "Refunded Quantity", - "description": "For refund charges, the quantity being refunded. For non-refund charges, the total quantity refunded (possibly over multiple refunds)." - }, - "credit_applied": { - "type": ["null", "number"], - "format": "float", - "title": "Credit Applied", - "description": "The amount of credit from this line item that was applied to the invoice." - }, - "shipping_address": { - "type": ["null", "object"], - "properties": { - "id": { - "type": "string", - "title": "Shipping Address ID", - "maxLength": 13, - "readOnly": true - } - } - }, - "start_date": { - "type": ["null", "string"], - "format": "date-time", - "title": "Start date", - "description": "If an end date is present, this is value indicates the beginning of a billing time range. If no end date is present it indicates billing for a specific date." - }, - "end_date": { - "type": ["null", "string"], - "format": "date-time", - "title": "End date", - "description": "If this date is provided, it indicates the end of a time range." - }, - "created_at": { - "type": "string", - "format": "date-time", - "title": "Created at", - "description": "When the line item was created." - }, - "updated_at": { - "type": "string", - "format": "date-time", - "title": "Last updated at", - "description": "When the line item was last changed." - } - } + "$ref": "line_items.json" } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/measured_units.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/measured_units.json index abc96f8afead..7865d44d3079 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/measured_units.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/measured_units.json @@ -6,6 +6,9 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "name": { "type": ["null", "string"], "maxLength": 256 diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/plans.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/plans.json index ed7fa91d786f..aabac321be53 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/plans.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/plans.json @@ -6,6 +6,9 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "code": { "type": ["null", "string"], "maxLength": 256 @@ -45,6 +48,48 @@ "auto_renew": { "type": ["null", "boolean"] }, + "pricing_model": { + "type": ["null", "string"] + }, + "ramp_intervals": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "starting_billing_cycle": { + "type": ["null", "integer"] + }, + "currencies": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "currency": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "number"] + } + } + } + } + } + } + }, + "custom_fields": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, "accounting_code": { "type": ["null", "string"], "maxLength": 256 diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/account_details.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/account_details.json new file mode 100644 index 000000000000..9d3dc5d71945 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/account_details.json @@ -0,0 +1,35 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": "string" + }, + "object": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, + "company": { + "type": ["null", "string"] + }, + "parent_account_id": { + "type": ["null", "string"] + }, + "bill_to": { + "type": ["null", "string"] + }, + "dunning_campaign_id": { + "type": ["null", "string"] + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/billing_infos.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/billing_infos.json new file mode 100644 index 000000000000..dbf207f589b4 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/billing_infos.json @@ -0,0 +1,213 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "id": { + "type": "string", + "maxLength": 13, + "readOnly": true + }, + "object": { + "type": ["null", "string"] + }, + "account_id": { + "type": "string", + "maxLength": 13, + "readOnly": true + }, + "first_name": { + "type": ["null", "string"], + "maxLength": 50 + }, + "last_name": { + "type": ["null", "string"], + "maxLength": 50 + }, + "company": { + "type": ["null", "string"], + "maxLength": 100 + }, + "address": { + "type": "object", + "properties": { + "phone": { + "type": ["null", "string"], + "title": "Phone number", + "maxLength": 256 + }, + "street1": { + "type": ["null", "string"], + "title": "Street 1", + "maxLength": 256 + }, + "street2": { + "type": ["null", "string"], + "title": "Street 2", + "maxLength": 256 + }, + "city": { + "type": ["null", "string"], + "title": "City", + "maxLength": 256 + }, + "region": { + "type": ["null", "string"], + "title": "State/Province", + "description": "State or province.", + "maxLength": 256 + }, + "postal_code": { + "type": ["null", "string"], + "title": "Zip/Postal code", + "description": "Zip or postal code.", + "maxLength": 256 + }, + "country": { + "type": ["null", "string"], + "title": "Country", + "description": "Country, 2-letter ISO 3166-1 alpha-2 code.", + "maxLength": 2 + } + } + }, + "vat_number": { + "type": ["null", "string"], + "description": "Customer's VAT number (to avoid having the VAT applied). This is only used for automatically collected invoices.", + "maxLength": 20 + }, + "valid": { + "type": "boolean", + "readOnly": true + }, + "payment_method": { + "type": "object", + "properties": { + "card_type": { + "description": "Visa, MasterCard, American Express, Discover, JCB, etc.", + "type": ["null", "string"], + "maxLength": 256 + }, + "object": { + "type": ["null", "string"] + }, + "first_six": { + "type": ["null", "string"], + "description": "Credit card number's first six digits.", + "maxLength": 6 + }, + "last_four": { + "type": ["null", "string"], + "description": "Credit card number's last four digits. Will refer to bank account if payment method is ACH.", + "maxLength": 4 + }, + "last_two": { + "type": ["null", "string"], + "description": "The IBAN bank account's last two digits.", + "maxLength": 2 + }, + "exp_month": { + "type": ["null", "integer"], + "description": "Expiration month.", + "maxLength": 2 + }, + "exp_year": { + "type": ["null", "integer"], + "description": "Expiration year.", + "maxLength": 4 + }, + "gateway_token": { + "type": ["null", "string"], + "description": "A token used in place of a credit card in order to perform transactions.", + "maxLength": 50 + }, + "cc_bin_country": { + "type": ["null", "string"], + "description": "The 2-letter ISO 3166-1 alpha-2 country code associated with the credit card BIN, if known by Recurly. Available on the BillingInfo object only. Available when the BIN country lookup feature is enabled.", + "maxLength": 256 + }, + "gateway_code": { + "type": ["null", "string"], + "description": "An identifier for a specific payment gateway.", + "maxLength": 13 + }, + "billing_agreement_id": { + "type": ["null", "string"], + "description": "Billing Agreement identifier. Only present for Amazon or Paypal payment methods.", + "maxLength": 256 + }, + "name_on_account": { + "type": ["null", "string"], + "description": "The name associated with the bank account.", + "maxLength": 256 + }, + "account_type": { + "description": "The bank account type. Only present for ACH payment methods.", + "type": ["null", "string"], + "maxLength": 256 + }, + "routing_number": { + "type": ["null", "string"], + "description": "The bank account's routing number. Only present for ACH payment methods.", + "maxLength": 256 + }, + "routing_number_bank": { + "type": ["null", "string"], + "description": "The bank name of this routing number.", + "maxLength": 256 + } + } + }, + "fraud": { + "type": ["null", "object"], + "title": "Fraud information", + "description": "Most recent fraud result.", + "readOnly": true, + "properties": { + "score": { + "type": ["null", "integer"], + "title": "Kount score" + }, + "decision": { + "title": "Kount decision", + "maxLength": 10, + "type": ["null", "string"] + }, + "risk_rules_triggered": { + "type": "object", + "title": "Kount rules" + } + } + }, + "primary_payment_method": { + "type": "boolean", + "description": "The `primary_payment_method` field is used to indicate the primary billing info on the account. The first billing info created on an account will always become primary. This payment method will be used" + }, + "backup_payment_method": { + "type": "boolean", + "description": "The `backup_payment_method` field is used to indicate a billing info as a backup on the account that will be tried if the initial billing info used for an invoice is declined." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the billing information was created.", + "readOnly": true + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "When the billing information was last changed.", + "readOnly": true + }, + "updated_by": { + "type": ["null", "object"], + "properties": { + "ip": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupon_redemptions.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupon_redemptions.json new file mode 100644 index 000000000000..e74f00e93f57 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupon_redemptions.json @@ -0,0 +1,85 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "coupon": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "discount": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "percent": { + "type": ["null", "integer"] + }, + "currencies": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "currency": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + } + } + }, + "trial": { + "type": ["null", "object"], + "properties": { + "unit": { + "type": ["null", "string"] + }, + "length": { + "type": ["null", "integer"] + } + } + } + } + }, + "coupon_type": { + "type": ["null", "string"] + }, + "expired_at": { + "type": ["null", "string"], + "format": "date-time" + } + } + }, + "state": { + "type": ["null", "string"] + }, + "discounted": { + "type": ["null", "number"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupons.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupons.json new file mode 100644 index 000000000000..50b91db59b4f --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/coupons.json @@ -0,0 +1,194 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "id": { + "type": ["null", "string"], + "maxLength": 13 + }, + "object": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"], + "maxLength": 256 + }, + "name": { + "type": ["null", "string"], + "maxLength": 256 + }, + "state": { + "type": ["null", "string"], + "maxLength": 256 + }, + "max_redemptions": { + "type": ["null", "number"] + }, + "max_redemptions_per_account": { + "type": ["null", "number"] + }, + "unique_coupon_codes_count": { + "type": ["null", "number"] + }, + "unique_code_template": { + "type": ["null", "string"], + "maxLength": 256 + }, + "unique_coupon_code": { + "$ref": "unique_coupons.json" + }, + "duration": { + "type": ["null", "string"], + "maxLength": 256 + }, + "temporal_amount": { + "type": ["null", "number"] + }, + "temporal_unit": { + "type": ["null", "string"], + "maxLength": 256 + }, + "free_trial_unit": { + "type": ["null", "string"], + "maxLength": 256 + }, + "free_trial_amount": { + "type": ["null", "number"] + }, + "applies_to_all_plans": { + "type": ["null", "boolean"] + }, + "applies_to_all_items": { + "type": ["null", "boolean"] + }, + "applies_to_non_plan_charges": { + "type": ["null", "boolean"] + }, + "plans": { + "type": ["null", "array"], + "title": "Plans", + "description": "A list of plans for which this coupon applies. This will be `null` if `applies_to_all_plans=true`.", + "items": { + "type": "object", + "title": "Plan mini details", + "description": "Just the important parts.", + "properties": { + "id": { + "type": "string", + "title": "Plan ID", + "maxLength": 13, + "readOnly": true + }, + "code": { + "type": "string", + "title": "Plan code", + "description": "Unique code to identify the plan. This is used in Hosted Payment Page URLs and in the invoice exports.", + "maxLength": 13 + } + } + } + }, + "items": { + "type": ["null", "array"], + "title": "Items", + "description": "A list of items for which this coupon applies. This will be\n`null` if `applies_to_all_items=true`.\n", + "items": { + "type": ["null", "object"], + "title": "Item mini details", + "description": "Just the important parts.", + "properties": { + "id": { + "type": "string", + "title": "Item ID", + "maxLength": 13, + "readOnly": true + } + } + } + }, + "redemption_resource": { + "type": ["null", "string"], + "maxLength": 256 + }, + "discount": { + "type": ["null", "object"], + "description": "Details of the discount a coupon applies. Will contain a `type`\nproperty and one of the following properties: `percent`, `fixed`, `trial`.\n", + "properties": { + "type": { + "type": "string", + "maxLength": 256 + }, + "percent": { + "description": "This is only present when `type=percent`.", + "type": "integer" + }, + "currencies": { + "type": "array", + "description": "This is only present when `type=fixed`.", + "items": { + "type": ["null", "object"], + "properties": { + "currency": { + "type": "string", + "title": "Currency", + "description": "3-letter ISO 4217 currency code.", + "maxLength": 3 + }, + "amount": { + "type": "number", + "format": "float", + "title": "Discount Amount", + "description": "Value of the fixed discount that this coupon applies." + } + } + } + }, + "trial": { + "type": "object", + "description": "This is only present when `type=free_trial`.", + "properties": { + "unit": { + "title": "Trial unit", + "description": "Temporal unit of the free trial", + "type": "string", + "maxLength": 256 + }, + "length": { + "type": "integer", + "title": "Trial length", + "description": "Trial length measured in the units specified by the sibling `unit` property" + } + } + } + } + }, + "coupon_type": { + "type": ["null", "string"], + "maxLength": 256 + }, + "hosted_page_description": { + "type": ["null", "string"], + "maxLength": 1024 + }, + "invoice_description": { + "type": ["null", "string"], + "maxLength": 1024 + }, + "redeem_by": { + "type": ["null", "string"], + "maxLength": 256 + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "updated_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "expired_at": { + "type": ["null", "string"], + "format": "date-time" + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/external_accounts.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/external_accounts.json new file mode 100644 index 000000000000..29e6292263b7 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/external_accounts.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "object": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "external_account_code": { + "type": ["null", "string"] + }, + "external_connection_type": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/line_items.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/line_items.json new file mode 100644 index 000000000000..33e1fb8809d8 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/line_items.json @@ -0,0 +1,293 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": ["null", "object"], + "title": "Line item", + "properties": { + "id": { + "type": "string", + "title": "Line item ID", + "maxLength": 13 + }, + "object": { + "type": ["null", "string"] + }, + "uuid": { + "type": "string", + "title": "UUID", + "description": "The UUID is useful for matching data with the CSV exports and building URLs into Recurly's UI.", + "maxLength": 32 + }, + "type": { + "type": "string", + "title": "Line item type", + "description": "Charges are positive line items that debit the account. Credits are negative line items that credit the account.", + "maxLength": 256 + }, + "item_code": { + "type": ["null", "string"], + "title": "Item Code", + "description": "Unique code to identify an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", + "maxLength": 50 + }, + "item_id": { + "type": ["null", "string"], + "title": "Item ID", + "description": "System-generated unique identifier for an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", + "maxLength": 13 + }, + "external_sku": { + "type": ["null", "string"], + "title": "External SKU", + "description": "Optional Stock Keeping Unit assigned to an item. Available when the Credit Invoices and Subscription Billing Terms features are enabled.", + "maxLength": 50 + }, + "revenue_schedule_type": { + "type": ["null", "string"], + "title": "Revenue schedule type", + "maxLength": 256 + }, + "state": { + "type": "string", + "title": "Current state of the line item", + "description": "Pending line items are charges or credits on an account that have not been applied to an invoice yet. Invoiced line items will always have an `invoice_id` value.", + "maxLength": 256 + }, + "legacy_category": { + "type": ["null", "string"], + "title": "Legacy category", + "description": "Category to describe the role of a line item on a legacy invoice:\n- \"charges\" refers to charges being billed for on this invoice.\n- \"credits\" refers to refund or proration credits. This portion of the invoice can be considered a credit memo.\n- \"applied_credits\" refers to previous credits applied to this invoice. See their original_line_item_id to determine where the credit first originated.\n- \"carryforwards\" can be ignored. They exist to consume any remaining credit balance. A new credit with the same amount will be created and placed back on the account.\n" + }, + "account": { + "$ref": "account_details.json" + }, + "bill_for_account_id": { + "type": "string", + "title": "Bill For Account ID", + "maxLength": 13, + "description": "The UUID of the account responsible for originating the line item." + }, + "subscription_id": { + "type": ["null", "string"], + "title": "Subscription ID", + "description": "If the line item is a charge or credit for a subscription, this is its ID.", + "maxLength": 13 + }, + "plan_id": { + "type": ["null", "string"], + "title": "Plan ID", + "description": "If the line item is a charge or credit for a plan or add-on, this is the plan's ID.", + "maxLength": 13 + }, + "plan_code": { + "type": ["null", "string"], + "title": "Plan code", + "description": "If the line item is a charge or credit for a plan or add-on, this is the plan's code.", + "maxLength": 50 + }, + "add_on_id": { + "type": ["null", "string"], + "title": "Add-on ID", + "description": "If the line item is a charge or credit for an add-on this is its ID.", + "maxLength": 13 + }, + "add_on_code": { + "type": ["null", "string"], + "title": "Add-on code", + "description": "If the line item is a charge or credit for an add-on, this is its code.", + "maxLength": 50 + }, + "invoice_id": { + "type": ["null", "string"], + "title": "Invoice ID", + "description": "Once the line item has been invoiced this will be the invoice's ID.", + "maxLength": 13 + }, + "invoice_number": { + "type": ["null", "string"], + "title": "Invoice number", + "description": "Once the line item has been invoiced this will be the invoice's number. If VAT taxation and the Country Invoice Sequencing feature are enabled, invoices will have country-specific invoice numbers for invoices billed to EU countries (ex: FR1001). Non-EU invoices will continue to use the site-level invoice number sequence.", + "maxLength": 256 + }, + "previous_line_item_id": { + "type": ["null", "string"], + "title": "Previous line item ID", + "description": "Will only have a value if the line item is a credit created from a previous credit, or if the credit was created from a charge refund.", + "maxLength": 13 + }, + "original_line_item_invoice_id": { + "type": ["null", "string"], + "title": "Original line item's invoice ID", + "description": "The invoice where the credit originated. Will only have a value if the line item is a credit created from a previous credit, or if the credit was created from a charge refund.", + "maxLength": 13 + }, + "origin": { + "type": "string", + "title": "Origin of line item", + "description": "A credit created from an original charge will have the value of the charge's origin.", + "maxLength": 256 + }, + "accounting_code": { + "type": "string", + "title": "Accounting code", + "description": "Internal accounting code to help you reconcile your revenue to the correct ledger. Line items created as part of a subscription invoice will use the plan or add-on's accounting code, otherwise the value will only be present if you define an accounting code when creating the line item.", + "maxLength": 20 + }, + "product_code": { + "type": "string", + "title": "Product code", + "description": "For plan-related line items this will be the plan's code, for add-on related line items it will be the add-on's code. For item-related line items it will be the item's `external_sku`.", + "maxLength": 50 + }, + "credit_reason_code": { + "type": ["null", "string"], + "title": "Credit reason code", + "description": "The reason the credit was given when line item is `type=credit`.", + "default": "general", + "maxLength": 256 + }, + "currency": { + "type": "string", + "title": "Currency", + "description": "3-letter ISO 4217 currency code.", + "maxLength": 3 + }, + "amount": { + "type": "number", + "format": "float", + "title": "Total after discounts and taxes", + "description": "`(quantity * unit_amount) - (discount + tax)`" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description that appears on the invoice. For subscription related items this will be filled in automatically.", + "maxLength": 255 + }, + "quantity": { + "type": "integer", + "title": "Quantity", + "description": "This number will be multiplied by the unit amount to compute the subtotal before any discounts or taxes.", + "default": 1 + }, + "unit_amount": { + "type": "number", + "format": "float", + "title": "Unit amount", + "description": "Positive amount for a charge, negative amount for a credit." + }, + "unit_amount_decimal": { + "type": ["null", "string"], + "title": "Unit amount decimal", + "description": "Positive amount for a charge, negative amount for a credit." + }, + "subtotal": { + "type": "number", + "format": "float", + "title": "Total before discounts and taxes", + "description": "`quantity * unit_amount`" + }, + "discount": { + "type": ["null", "number"], + "format": "float", + "title": "Discount", + "description": "The discount applied to the line item." + }, + "tax": { + "type": ["null", "number"], + "format": "float", + "title": "Tax", + "description": "The tax amount for the line item." + }, + "taxable": { + "type": "boolean", + "title": "Taxable?", + "description": "`true` if the line item is taxable, `false` if it is not." + }, + "tax_exempt": { + "type": "boolean", + "title": "Tax exempt?", + "description": "`true` exempts tax on charges, `false` applies tax on charges. If not defined, then defaults to the Plan and Site settings. This attribute does not work for credits (negative line items). Credits are always applied post-tax. Pre-tax discounts should use the Coupons feature." + }, + "tax_code": { + "type": ["null", "string"], + "title": "Tax code", + "description": "Used by Avalara, Vertex, and Recurly\u2019s EU VAT tax feature. The tax code values are specific to each tax system. If you are using Recurly\u2019s EU VAT feature you can use `unknown`, `physical`, or `digital`.", + "maxLength": 50 + }, + "tax_info": { + "$ref": "tax_info.json" + }, + "proration_rate": { + "type": ["null", "number"], + "format": "float", + "title": "Proration rate", + "description": "When a line item has been prorated, this is the rate of the proration. Proration rates were made available for line items created after March 30, 2017. For line items created prior to that date, the proration rate will be `null`, even if the line item was prorated.", + "minimum": 0, + "maximum": 1 + }, + "refund": { + "type": "boolean", + "title": "Refund?" + }, + "refunded_quantity": { + "type": ["null", "integer"], + "title": "Refunded Quantity", + "description": "For refund charges, the quantity being refunded. For non-refund charges, the total quantity refunded (possibly over multiple refunds)." + }, + "credit_applied": { + "type": ["null", "number"], + "format": "float", + "title": "Credit Applied", + "description": "The amount of credit from this line item that was applied to the invoice." + }, + "shipping_address": { + "type": ["null", "object"], + "properties": { + "id": { + "type": "string", + "title": "Shipping Address ID", + "maxLength": 13, + "readOnly": true + } + } + }, + "start_date": { + "type": ["null", "string"], + "format": "date-time", + "title": "Start date", + "description": "If an end date is present, this is value indicates the beginning of a billing time range. If no end date is present it indicates billing for a specific date." + }, + "end_date": { + "type": ["null", "string"], + "format": "date-time", + "title": "End date", + "description": "If this date is provided, it indicates the end of a time range." + }, + "custom_fields": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created at", + "description": "When the line item was created." + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Last updated at", + "description": "When the line item was last changed." + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/shipping_addresses.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/shipping_addresses.json new file mode 100644 index 000000000000..e0f8091cdbe6 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/shipping_addresses.json @@ -0,0 +1,91 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": ["null", "object"], + "properties": { + "id": { + "type": "string", + "title": "Shipping Address ID", + "maxLength": 13, + "readOnly": true + }, + "object": { + "type": ["null", "string"] + }, + "account_id": { + "type": "string", + "title": "Account ID", + "maxLength": 13, + "readOnly": true + }, + "nickname": { + "type": "string", + "maxLength": 255 + }, + "first_name": { + "type": "string", + "maxLength": 255 + }, + "last_name": { + "type": "string", + "maxLength": 255 + }, + "company": { + "type": "string", + "maxLength": 255 + }, + "email": { + "type": "string", + "maxLength": 255 + }, + "vat_number": { + "type": "string", + "maxLength": 20 + }, + "phone": { + "type": "string", + "maxLength": 30 + }, + "street1": { + "type": "string", + "maxLength": 255 + }, + "street2": { + "type": "string", + "maxLength": 255 + }, + "city": { + "type": "string", + "maxLength": 255 + }, + "region": { + "type": "string", + "maxLength": 255, + "description": "State or province." + }, + "postal_code": { + "type": "string", + "maxLength": 20, + "description": "Zip or postal code." + }, + "country": { + "type": "string", + "maxLength": 50, + "description": "Country, 2-letter ISO 3166-1 alpha-2 code." + }, + "geo_code": { + "type": ["null", "string"] + }, + "created_at": { + "type": "string", + "title": "Created at", + "format": "date-time", + "readOnly": true + }, + "updated_at": { + "type": "string", + "title": "Updated at", + "format": "date-time", + "readOnly": true + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/tax_info.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/tax_info.json new file mode 100644 index 000000000000..13502eb46241 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/tax_info.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "region": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "number"] + }, + "tax_details": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "region": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "number"] + }, + "tax": { + "type": ["null", "number"] + }, + "name": { + "type": ["null", "string"] + }, + "level": { + "type": ["null", "string"] + }, + "billable": { + "type": ["null", "boolean"] + } + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/unique_coupons.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/unique_coupons.json new file mode 100644 index 000000000000..1d2a0a3a117c --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/unique_coupons.json @@ -0,0 +1,66 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": ["null", "object"], + "description": "A unique coupon code for a bulk coupon.", + "properties": { + "id": { + "type": "string", + "title": "Unique Coupon Code ID", + "readOnly": true, + "maxLength": 13 + }, + "object": { + "type": "string" + }, + "code": { + "type": "string", + "title": "Coupon code", + "description": "The code the customer enters to redeem the coupon.", + "maxLength": 256 + }, + "state": { + "type": ["null", "string"], + "title": "State", + "description": "Indicates if the unique coupon code is redeemable or why not.", + "maxLength": 256 + }, + "bulk_coupon_id": { + "type": ["null", "string"], + "title": "Bulk Coupon ID", + "description": "The Coupon ID of the parent Bulk Coupon", + "readOnly": true, + "maxLength": 13 + }, + "bulk_coupon_code": { + "type": ["null", "string"], + "title": "Bulk Coupon code", + "description": "The Coupon code of the parent Bulk Coupon", + "maxLength": 256 + }, + "created_at": { + "type": "string", + "title": "Created at", + "format": "date-time", + "readOnly": true + }, + "updated_at": { + "type": "string", + "title": "Updated at", + "format": "date-time", + "readOnly": true + }, + "redeemed_at": { + "type": ["null", "string"], + "title": "Redeemed at", + "description": "The date and time the unique coupon code was redeemed.", + "format": "date-time", + "readOnly": true + }, + "expired_at": { + "type": ["null", "string"], + "title": "Expired at", + "description": "The date and time the coupon was expired early or reached its `max_redemptions`.", + "format": "date-time" + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/users.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/users.json new file mode 100644 index 000000000000..70b7c49ac122 --- /dev/null +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shared/users.json @@ -0,0 +1,33 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": "string" + }, + "object": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, + "time_zone": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time", + "airbyte_type": "timestamp_without_timezone" + }, + "deleted_at": { + "type": ["null", "string"], + "format": "date-time", + "airbyte_type": "timestamp_without_timezone" + } + } +} diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shipping_addresses.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shipping_addresses.json index 4860797be798..bcbb555d47a4 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shipping_addresses.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/shipping_addresses.json @@ -1,85 +1,3 @@ { - "$schema": "http://json-schema.org/schema#", - "type": "object", - "properties": { - "id": { - "type": "string", - "title": "Shipping Address ID", - "maxLength": 13, - "readOnly": true - }, - "account_id": { - "type": "string", - "title": "Account ID", - "maxLength": 13, - "readOnly": true - }, - "nickname": { - "type": "string", - "maxLength": 255 - }, - "first_name": { - "type": "string", - "maxLength": 255 - }, - "last_name": { - "type": "string", - "maxLength": 255 - }, - "company": { - "type": "string", - "maxLength": 255 - }, - "email": { - "type": "string", - "maxLength": 255 - }, - "vat_number": { - "type": "string", - "maxLength": 20 - }, - "phone": { - "type": "string", - "maxLength": 30 - }, - "street1": { - "type": "string", - "maxLength": 255 - }, - "street2": { - "type": "string", - "maxLength": 255 - }, - "city": { - "type": "string", - "maxLength": 255 - }, - "region": { - "type": "string", - "maxLength": 255, - "description": "State or province." - }, - "postal_code": { - "type": "string", - "maxLength": 20, - "description": "Zip or postal code." - }, - "country": { - "type": "string", - "maxLength": 50, - "description": "Country, 2-letter ISO 3166-1 alpha-2 code." - }, - "created_at": { - "type": "string", - "title": "Created at", - "format": "date-time", - "readOnly": true - }, - "updated_at": { - "type": "string", - "title": "Updated at", - "format": "date-time", - "readOnly": true - } - } + "$ref": "shipping_addresses.json" } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/subscriptions.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/subscriptions.json index eeed47064a7c..27c3b0ad4ea1 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/subscriptions.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/subscriptions.json @@ -6,20 +6,48 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "uuid": { "type": ["null", "string"], "maxLength": 32 }, "account": { - "type": "object", + "type": ["null", "object"], "properties": { "id": { "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "code": { "type": ["null", "string"], "maxLength": 256 + }, + "email": { + "type": ["null", "string"], + "maxLength": 256 + }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, + "company": { + "type": ["null", "string"] + }, + "parent_account_id": { + "type": ["null", "string"] + }, + "bill_to": { + "type": ["null", "string"] + }, + "dunning_campaign_id": { + "type": ["null", "string"] } } }, @@ -30,9 +58,15 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "code": { "type": ["null", "string"], "maxLength": 256 + }, + "name": { + "type": ["null", "string"] } } }, @@ -43,16 +77,11 @@ "shipping": { "type": ["null", "object"], "properties": { + "object": { + "type": ["null", "string"] + }, "address": { - "type": ["null", "object"], - "properties": { - "id": { - "type": "string", - "title": "Shipping Address ID", - "maxLength": 13, - "readOnly": true - } - } + "$ref": "shipping_addresses.json" }, "method": { "type": ["null", "object"], @@ -62,6 +91,15 @@ "title": "Shipping Method ID", "readOnly": true, "maxLength": 13 + }, + "object": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] } } }, @@ -70,6 +108,7 @@ } } }, + "coupon_redemptions": { "$ref": "coupon_redemptions.json" }, "pending_change": { "type": ["null", "object"], "title": "Subscription Change", @@ -153,6 +192,31 @@ "auto_renew": { "type": ["null", "boolean"] }, + "ramp_intervals": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "starting_billing_cycle": { + "type": ["null", "integer"] + }, + "remaining_billing_cycles": { + "type": ["null", "integer"] + }, + "starting_on": { + "type": ["null", "string"], + "format": "date-time" + }, + "ending_on": { + "type": ["null", "string"], + "format": "date-time" + }, + "unit_amount": { + "type": ["null", "number"] + } + } + } + }, "paused_at": { "type": ["null", "string"], "format": "date-time" @@ -171,6 +235,9 @@ "unit_amount": { "type": ["null", "number"] }, + "tax_inclusive": { + "type": ["null", "boolean"] + }, "quantity": { "type": ["null", "number"] }, @@ -206,61 +273,7 @@ "type": ["null", "number"] }, "tax_info": { - "type": ["null", "object"], - "title": "Tax info", - "properties": { - "type": { - "type": "string", - "title": "Type", - "description": "Provides the tax type as \"vat\" for EU VAT, \"usst\" for U.S. Sales Tax, or the 2 letter country code for country level tax types like Canada, Australia, New Zealand, Israel, and all non-EU European countries.", - "maxLength": 256 - }, - "region": { - "type": "string", - "title": "Region", - "description": "Provides the tax region applied on an invoice. For U.S. Sales Tax, this will be the 2 letter state code. For EU VAT this will be the 2 letter country code. For all country level tax types, this will display the regional tax, like VAT, GST, or PST.", - "maxLength": 256 - }, - "rate": { - "type": "number", - "format": "float", - "title": "Rate" - }, - "tax_details": { - "type": ["null", "array"], - "description": "Provides additional tax details for Canadian Sales Tax when there is tax applied at both the country and province levels. This will only be populated for the Invoice response when fetching a single invoice and not for the InvoiceList or LineItem.", - "items": { - "type": "object", - "title": "Tax detail", - "properties": { - "type": { - "type": "string", - "title": "Type", - "description": "Provides the tax type for the region. For Canadian Sales Tax, this will be GST, HST, QST or PST.", - "maxLength": 256 - }, - "region": { - "type": "string", - "title": "Region", - "description": "Provides the tax region applied on an invoice. For Canadian Sales Tax, this will be either the 2 letter province code or country code.", - "maxLength": 256 - }, - "rate": { - "type": "number", - "format": "float", - "title": "Rate", - "description": "Provides the tax rate for the region." - }, - "tax": { - "type": "number", - "format": "float", - "title": "Tax", - "description": "The total tax applied for this tax type." - } - } - } - } - } + "$ref": "tax_info.json" }, "total": { "type": ["null", "number"] @@ -276,6 +289,9 @@ "net_terms": { "type": ["null", "number"] }, + "net_terms_type": { + "type": ["null", "string"] + }, "terms_and_conditions": { "type": ["null", "string"], "maxLength": 16384 @@ -288,6 +304,20 @@ "type": ["null", "string"], "maxLength": 1024 }, + "custom_fields": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } + } + } + }, "created_at": { "type": ["null", "string"], "format": "date-time" @@ -319,6 +349,20 @@ "billing_info_id": { "type": ["null", "string"], "maxLength": 13 + }, + "active_invoice_id": { + "type": ["null", "string"] + }, + "started_with_gift": { + "type": ["null", "boolean"] + }, + "converted_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "action_result": { + "type": ["null", "object"], + "additionalProperties": true } } } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/transactions.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/transactions.json index 660e28842f2f..7b06e0d76cb5 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/transactions.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/transactions.json @@ -1,11 +1,15 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", + "additionalProperties": true, "properties": { "id": { "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "uuid": { "type": ["null", "string"], "maxLength": 32 @@ -15,17 +19,7 @@ "maxLength": 13 }, "account": { - "type": "object", - "properties": { - "id": { - "type": ["null", "string"], - "maxLength": 13 - }, - "code": { - "type": ["null", "string"], - "maxLength": 256 - } - } + "$ref": "account_details.json" }, "invoice": { "type": ["null", "object"], @@ -37,6 +31,15 @@ "number": { "type": ["null", "string"], "maxLength": 256 + }, + "business_entity_id": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] } } }, @@ -47,9 +50,21 @@ "type": ["null", "string"], "maxLength": 13 }, + "object": { + "type": ["null", "string"] + }, "number": { "type": ["null", "string"], "maxLength": 256 + }, + "business_entity_id": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] } } }, @@ -126,6 +141,9 @@ "country": { "type": ["null", "string"], "maxLength": 256 + }, + "geo_code": { + "type": ["null", "string"] } } }, @@ -136,6 +154,9 @@ "payment_method": { "type": "object", "properties": { + "object": { + "type": ["null", "string"] + }, "card_type": { "type": ["null", "string"], "maxLength": 256 @@ -162,6 +183,9 @@ "type": ["null", "string"], "maxLength": 256 }, + "cc_bin_country": { + "type": ["null", "string"] + }, "gateway_code": { "type": ["null", "string"], "maxLength": 256 @@ -185,6 +209,9 @@ "routing_number_bank": { "type": ["null", "string"], "maxLength": 256 + }, + "username": { + "type": ["null", "string"] } } }, @@ -218,6 +245,15 @@ "id": { "type": ["null", "string"], "maxLength": 13 + }, + "object": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] } } }, @@ -266,6 +302,44 @@ "collected_at": { "type": ["null", "string"], "format": "date-time" + }, + "action_result": { + "type": ["null", "object"], + "additionalProperties": true + }, + "vat_number": { + "type": ["null", "string"] + }, + "fraud_info": { + "type": ["null", "object"], + "properties": { + "object": { + "type": ["null", "string"] + }, + "score": { + "type": ["null", "integer"] + }, + "decision": { + "type": ["null", "string"] + }, + "reference": { + "type": ["null", "string"] + }, + "risk_rules_triggered": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "code": { + "type": ["null", "string"] + }, + "message": { + "type": ["null", "string"] + } + } + } + } + } } } } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/unique_coupons.json b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/unique_coupons.json index 1d8d5522b27d..0458768570ff 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/unique_coupons.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/schemas/unique_coupons.json @@ -1,63 +1,3 @@ { - "$schema": "http://json-schema.org/schema#", - "type": "object", - "description": "A unique coupon code for a bulk coupon.", - "properties": { - "id": { - "type": "string", - "title": "Unique Coupon Code ID", - "readOnly": true, - "maxLength": 13 - }, - "code": { - "type": "string", - "title": "Coupon code", - "description": "The code the customer enters to redeem the coupon.", - "maxLength": 256 - }, - "state": { - "type": "string", - "title": "State", - "description": "Indicates if the unique coupon code is redeemable or why not.", - "maxLength": 256 - }, - "bulk_coupon_id": { - "type": ["null", "string"], - "title": "Bulk Coupon ID", - "description": "The Coupon ID of the parent Bulk Coupon", - "readOnly": true, - "maxLength": 13 - }, - "bulk_coupon_code": { - "type": ["null", "string"], - "title": "Bulk Coupon code", - "description": "The Coupon code of the parent Bulk Coupon", - "maxLength": 256 - }, - "created_at": { - "type": "string", - "title": "Created at", - "format": "date-time", - "readOnly": true - }, - "updated_at": { - "type": "string", - "title": "Updated at", - "format": "date-time", - "readOnly": true - }, - "redeemed_at": { - "type": ["null", "string"], - "title": "Redeemed at", - "description": "The date and time the unique coupon code was redeemed.", - "format": "date-time", - "readOnly": true - }, - "expired_at": { - "type": ["null", "string"], - "title": "Expired at", - "description": "The date and time the coupon was expired early or reached its `max_redemptions`.", - "format": "date-time" - } - } + "$ref": "unique_coupons.json" } diff --git a/airbyte-integrations/connectors/source-recurly/source_recurly/spec.json b/airbyte-integrations/connectors/source-recurly/source_recurly/spec.json index 02a427f7378b..d2135eb06551 100644 --- a/airbyte-integrations/connectors/source-recurly/source_recurly/spec.json +++ b/airbyte-integrations/connectors/source-recurly/source_recurly/spec.json @@ -5,7 +5,7 @@ "title": "Recurly Source Spec", "type": "object", "required": ["api_key"], - "additionalProperties": false, + "additionalProperties": true, "properties": { "api_key": { "type": "string", diff --git a/docs/integrations/sources/recurly.md b/docs/integrations/sources/recurly.md index fe5560d9bc5d..2fac238fb528 100644 --- a/docs/integrations/sources/recurly.md +++ b/docs/integrations/sources/recurly.md @@ -64,6 +64,7 @@ We recommend creating a restricted, read-only key specifically for Airbyte acces | Version | Date | Pull Request | Subject | |:--------|:-----------| :--------------------------------------------------------| :--------------------------------------------------------------------------------------- | +| 0.5.0 | 2024-02-22 | [34622](https://github.com/airbytehq/airbyte/pull/34622) | Republish connector using base image/Poetry, update schemas | | 0.4.1 | 2022-06-10 | [13685](https://github.com/airbytehq/airbyte/pull/13685) | Add state_checkpoint_interval to Recurly stream | | 0.4.0 | 2022-01-28 | [9866](https://github.com/airbytehq/airbyte/pull/9866) | Revamp Recurly Schema and add more resources | | 0.3.2 | 2022-01-20 | [8617](https://github.com/airbytehq/airbyte/pull/8617) | Update connector fields title/description | From b2b9b7fa219940c6f3dad46edc5d85cc1fa967c1 Mon Sep 17 00:00:00 2001 From: Stephane Geneix <147216312+stephane-airbyte@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:12:28 -0800 Subject: [PATCH 65/74] reduce interrupt and shutdown delays to 1 minutes and 2 minutes when stopping a connector (initially set at 60minutes and 70minutes) (#35527) Fixes #32348 discussed here : https://airbytehq-team.slack.com/archives/C02U2SSHP9S/p1708552465201999 --- airbyte-cdk/java/airbyte-cdk/README.md | 4 +- .../integrations/base/IntegrationRunner.java | 40 +++++++++++-------- .../connectors/source-mysql/build.gradle | 2 +- .../connectors/source-mysql/metadata.yaml | 2 +- docs/integrations/sources/mysql.md | 3 +- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index fee7d0f96374..adf174f5a256 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -167,7 +167,7 @@ MavenLocal debugging steps: | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| | 0.23.2 | 2024-02-22 | [\#35385](https://github.com/airbytehq/airbyte/pull/35342) | Bugfix: inverted logic of disableTypeDedupe flag | -| 0.23.1 | 2024-02-22 | [\#35527](https://github.com/airbytehq/airbyte/pull/35527) | reduce shutdown timeouts | +| 0.23.1 | 2024-02-22 | [\#35527](https://github.com/airbytehq/airbyte/pull/35527) | reduce shutdow timeouts | | 0.23.0 | 2024-02-22 | [\#35342](https://github.com/airbytehq/airbyte/pull/35342) | Consolidate and perform upfront gathering of DB metadata state | | 0.21.4 | 2024-02-21 | [\#35511](https://github.com/airbytehq/airbyte/pull/35511) | Reduce CDC state compression limit to 1MB | | 0.21.3 | 2024-02-20 | [\#35394](https://github.com/airbytehq/airbyte/pull/35394) | Add Junit progress information to the test logs | @@ -261,4 +261,4 @@ MavenLocal debugging steps: | 0.1.1 | 2023-09-28 | [\#30835](https://github.com/airbytehq/airbyte/pull/30835) | JDBC destinations now avoid staging area name collisions by using the raw table name as the stage name. (previously we used the stream name as the stage name) | | 0.1.0 | 2023-09-27 | [\#30445](https://github.com/airbytehq/airbyte/pull/30445) | First launch, including shared classes for all connectors. | | 0.0.2 | 2023-08-21 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Version bump only (no other changes). | -| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | \ No newline at end of file +| 0.0.1 | 2023-08-08 | [\#28687](https://github.com/airbytehq/airbyte/pull/28687) | Initial release for testing. | diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/IntegrationRunner.java b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/IntegrationRunner.java index 8da1ff8588aa..8fd71f3875b2 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/IntegrationRunner.java +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/java/io/airbyte/cdk/integrations/base/IntegrationRunner.java @@ -67,8 +67,8 @@ public class IntegrationRunner { static final Predicate ORPHANED_THREAD_FILTER = runningThread -> !runningThread.getName().equals(Thread.currentThread().getName()) && !runningThread.isDaemon() && !TYPE_AND_DEDUPE_THREAD_NAME.equals(runningThread.getName()); - public static final int INTERRUPT_THREAD_DELAY_MINUTES = 60; - public static final int EXIT_THREAD_DELAY_MINUTES = 70; + public static final int INTERRUPT_THREAD_DELAY_MINUTES = 1; + public static final int EXIT_THREAD_DELAY_MINUTES = 2; public static final int FORCED_EXIT_CODE = 2; @@ -189,11 +189,7 @@ private void runInternal(final IntegrationConfig parsed) throws Exception { try (final SerializedAirbyteMessageConsumer consumer = destination.getSerializedMessageConsumer(config, catalog, outputRecordCollector)) { consumeWriteStream(consumer); } finally { - stopOrphanedThreads(EXIT_HOOK, - INTERRUPT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES, - EXIT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES); + stopOrphanedThreads(); } } default -> throw new IllegalStateException("Unexpected value: " + parsed.getCommand()); @@ -263,11 +259,7 @@ private void readConcurrent(final JsonNode config, final ConfiguredAirbyteCatalo LOGGER.error("Unable to perform concurrent read.", e); throw e; } finally { - stopOrphanedThreads(EXIT_HOOK, - INTERRUPT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES, - EXIT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES); + stopOrphanedThreads(); } } @@ -275,11 +267,7 @@ private void readSerial(final JsonNode config, final ConfiguredAirbyteCatalog ca try (final AutoCloseableIterator messageIterator = source.read(config, catalog, stateOptional.orElse(null))) { produceMessages(messageIterator, outputRecordCollector); } finally { - stopOrphanedThreads(EXIT_HOOK, - INTERRUPT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES, - EXIT_THREAD_DELAY_MINUTES, - TimeUnit.MINUTES); + stopOrphanedThreads(); } } @@ -335,6 +323,23 @@ static void consumeWriteStream(final SerializedAirbyteMessageConsumer consumer, } } + /** + * Stops any non-daemon threads that could block the JVM from exiting when the main thread is done. + * + * If any active non-daemon threads would be left as orphans, this method will schedule some + * interrupt/exit hooks after giving it some time delay to close up properly. It is generally + * preferred to have a proper closing sequence from children threads instead of interrupting or + * force exiting the process, so this mechanism serve as a fallback while surfacing warnings in logs + * for maintainers to fix the code behavior instead. + */ + static void stopOrphanedThreads() { + stopOrphanedThreads(EXIT_HOOK, + INTERRUPT_THREAD_DELAY_MINUTES, + TimeUnit.MINUTES, + EXIT_THREAD_DELAY_MINUTES, + TimeUnit.MINUTES); + } + /** * Stops any non-daemon threads that could block the JVM from exiting when the main thread is done. *

@@ -343,6 +348,7 @@ static void consumeWriteStream(final SerializedAirbyteMessageConsumer consumer, * preferred to have a proper closing sequence from children threads instead of interrupting or * force exiting the process, so this mechanism serve as a fallback while surfacing warnings in logs * for maintainers to fix the code behavior instead. + *

* * @param exitHook The {@link Runnable} exit hook to execute for any orphaned threads. * @param interruptTimeDelay The time to delay execution of the orphaned thread interrupt attempt. diff --git a/airbyte-integrations/connectors/source-mysql/build.gradle b/airbyte-integrations/connectors/source-mysql/build.gradle index daeccabc9ec1..c0f1e6ef5114 100644 --- a/airbyte-integrations/connectors/source-mysql/build.gradle +++ b/airbyte-integrations/connectors/source-mysql/build.gradle @@ -6,7 +6,7 @@ plugins { } airbyteJavaConnector { - cdkVersionRequired = '0.21.4' + cdkVersionRequired = '0.23.1' features = ['db-sources'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/source-mysql/metadata.yaml b/airbyte-integrations/connectors/source-mysql/metadata.yaml index 761f7233b935..f80f0c555620 100644 --- a/airbyte-integrations/connectors/source-mysql/metadata.yaml +++ b/airbyte-integrations/connectors/source-mysql/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: 435bb9a5-7887-4809-aa58-28c27df0d7ad - dockerImageTag: 3.3.10 + dockerImageTag: 3.3.11 dockerRepository: airbyte/source-mysql documentationUrl: https://docs.airbyte.com/integrations/sources/mysql githubIssueLabel: source-mysql diff --git a/docs/integrations/sources/mysql.md b/docs/integrations/sources/mysql.md index d109a13a2847..26aafa4f12df 100644 --- a/docs/integrations/sources/mysql.md +++ b/docs/integrations/sources/mysql.md @@ -223,7 +223,8 @@ Any database or table encoding combination of charset and collation is supported | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| -| 3.3.10 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | +| 3.3.11 | 2024-02-23 | [35527](https://github.com/airbytehq/airbyte/pull/35527) | Adopt 0.23.1 and shutdown timeouts. | +| 3.3.10 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | | 3.3.9 | 2024-02-21 | [35525](https://github.com/airbytehq/airbyte/pull/35338) | Adopt 0.21.4 and reduce cdc state compression threshold to 1MB. | | 3.3.8 | 2024-02-20 | [35338](https://github.com/airbytehq/airbyte/pull/35338) | Add config to throw an error on invalid CDC position. | | 3.3.7 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | From 3918dc29bc34201238f3e070be7e00c97a7c21b8 Mon Sep 17 00:00:00 2001 From: Christo Grabowski <108154848+ChristoGrab@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:40:51 -0500 Subject: [PATCH 66/74] Docs: Add depecration notices to sunsetting connectors (#35446) --- docs/integrations/sources/appstore.md | 15 +++++++++++++++ docs/integrations/sources/courier.md | 14 ++++++++++++++ docs/integrations/sources/dv-360.md | 14 ++++++++++++++ docs/integrations/sources/kustomer-singer.md | 14 ++++++++++++++ docs/integrations/sources/search-metrics.md | 15 +++++++++++++++ docs/integrations/sources/talkdesk-explore.md | 15 +++++++++++++++ docs/integrations/sources/zuora.md | 14 ++++++++++++++ 7 files changed, 101 insertions(+) diff --git a/docs/integrations/sources/appstore.md b/docs/integrations/sources/appstore.md index b8acae44e28c..a99893048417 100644 --- a/docs/integrations/sources/appstore.md +++ b/docs/integrations/sources/appstore.md @@ -1,5 +1,20 @@ # Appstore +:::warning + +## Deprecation Notice + +The Appstore source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + + ## Sync overview This source can sync data for the [Appstore API](https://developer.apple.com/documentation/appstoreconnectapi). It supports only Incremental syncs. The Appstore API is available for [many types of services](https://developer.apple.com/documentation/appstoreconnectapi). Currently, this API supports syncing Sales and Trends reports. If you'd like to sync data from other endpoints, please create an issue on Github. diff --git a/docs/integrations/sources/courier.md b/docs/integrations/sources/courier.md index 265e72520974..8f0b9ed55c3c 100644 --- a/docs/integrations/sources/courier.md +++ b/docs/integrations/sources/courier.md @@ -1,5 +1,19 @@ # Courier +:::warning + +## Deprecation Notice + +The Courier source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + This page contains the setup guide and reference information for the [Courier](https://www.courier.com/) source connector. ## Prerequisites diff --git a/docs/integrations/sources/dv-360.md b/docs/integrations/sources/dv-360.md index b3c095f4691c..ebdcad8d0410 100644 --- a/docs/integrations/sources/dv-360.md +++ b/docs/integrations/sources/dv-360.md @@ -1,5 +1,19 @@ # Display & Video 360 +:::warning + +## Deprecation Notice + +The Display & Video 360 source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + Google DoubleClick Bid Manager (DBM) is the API that enables developers to manage Queries and retrieve Reports from Display & Video 360. DoubleClick Bid Manager API `v1.1` is the latest available and recommended version. diff --git a/docs/integrations/sources/kustomer-singer.md b/docs/integrations/sources/kustomer-singer.md index 5fc12662e4e9..60cf45ce7f9a 100644 --- a/docs/integrations/sources/kustomer-singer.md +++ b/docs/integrations/sources/kustomer-singer.md @@ -1,5 +1,19 @@ # Kustomer +:::warning + +## Deprecation Notice + +The Kustomer source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + ## Sync overview The Kustomer source supports both Full Refresh and Incremental syncs. You can choose if this connector will copy only the new or updated data, or all rows in the tables and columns you set up for replication, every time a sync is run. diff --git a/docs/integrations/sources/search-metrics.md b/docs/integrations/sources/search-metrics.md index 5d49b4bdb967..19ae17af87ba 100644 --- a/docs/integrations/sources/search-metrics.md +++ b/docs/integrations/sources/search-metrics.md @@ -1,5 +1,20 @@ # SearchMetrics +:::warning + +## Deprecation Notice + +The SearchMetrics source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + + ## Overview The SearchMetrics source supports both Full Refresh and Incremental syncs. You can choose if this connector will copy only the new or updated data, or all rows in the tables and columns you set up for replication, every time a sync is run. diff --git a/docs/integrations/sources/talkdesk-explore.md b/docs/integrations/sources/talkdesk-explore.md index b9c8ba54d1c6..74b3f89df4ab 100644 --- a/docs/integrations/sources/talkdesk-explore.md +++ b/docs/integrations/sources/talkdesk-explore.md @@ -1,5 +1,20 @@ # Talkdesk Explore +:::warning + +## Deprecation Notice + +The Talkdesk Explore source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + + ## Overview Talkdesk is a software for contact center operations. diff --git a/docs/integrations/sources/zuora.md b/docs/integrations/sources/zuora.md index 86ce852107fc..b0c5f019d967 100644 --- a/docs/integrations/sources/zuora.md +++ b/docs/integrations/sources/zuora.md @@ -1,5 +1,19 @@ # Zuora +:::warning + +## Deprecation Notice + +The Zuora source connector is scheduled for deprecation on March 5th, 2024 due to incompatibility with upcoming platform updates as we prepare to launch Airbyte 1.0. This means it will no longer be supported or available for use in Airbyte. + +This connector does not support new per-stream features which are vital for ensuring data integrity in Airbyte's synchronization processes. Without these capabilities, we cannot enforce our standards of reliability and correctness for data syncing operations. + +### Recommended Actions + +Users who still wish to sync data from this connector are advised to explore creating a custom connector as an alternative to continue their data synchronization needs. For guidance, please visit our [Custom Connector documentation](https://docs.airbyte.com/connector-development/). + +::: + ## Sync overview The Zuora source supports both Full Refresh and Incremental syncs. You can choose if this connector will copy only the new or updated data, or all rows in the tables and columns you set up for replication, every time a sync is run. From a6b3f0c96e3132804dc71392b52c4599aedace70 Mon Sep 17 00:00:00 2001 From: Bindi Pankhudi Date: Sun, 25 Feb 2024 09:10:47 -0800 Subject: [PATCH 67/74] Cleaned up PyAibyte docs (PR # 35603) (#35603) Co-authored-by: bindipankhudi --- .../airbyte-lib-high-level-architecture.svg | 2 +- .../airbyte-lib/getting-started.mdx | 23 ++++++++++++------ docs/using-airbyte/airbyte-lib/reference.mdx | 15 ------------ docusaurus/redirects.yml | 3 +++ docusaurus/static/img/pyairbyte-logo-dark.png | Bin 0 -> 8055 bytes 5 files changed, 20 insertions(+), 23 deletions(-) delete mode 100644 docs/using-airbyte/airbyte-lib/reference.mdx create mode 100644 docusaurus/static/img/pyairbyte-logo-dark.png diff --git a/docs/assets/docs/airbyte-lib-high-level-architecture.svg b/docs/assets/docs/airbyte-lib-high-level-architecture.svg index 70f0f46bc458..832788f0cc8b 100644 --- a/docs/assets/docs/airbyte-lib-high-level-architecture.svg +++ b/docs/assets/docs/airbyte-lib-high-level-architecture.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/using-airbyte/airbyte-lib/getting-started.mdx b/docs/using-airbyte/airbyte-lib/getting-started.mdx index 59c3b2907035..50baa2320b10 100644 --- a/docs/using-airbyte/airbyte-lib/getting-started.mdx +++ b/docs/using-airbyte/airbyte-lib/getting-started.mdx @@ -1,19 +1,19 @@ import AirbyteLibConnectors from '@site/src/components/AirbyteLibConnectors'; -# Getting Started with AirbyteLib (Beta) +# Getting Started with PyAirbyte (Beta) -AirbyteLib is a library that provides a set of utilities to use Airbyte connectors in Python. It is meant to be used in situations where setting up an Airbyte server or cloud account is not possible or desirable, for example in a Jupyter notebook or when iterating on early prototypes on a developer's workstation. +PyAirbyte is a library that provides a set of utilities to use Airbyte connectors in Python. It is meant to be used in situations where setting up an Airbyte server or cloud account is not possible or desirable, for example in a Jupyter notebook or when iterating on early prototypes on a developer's workstation. ## Installation ```bash -pip install airbyte-lib +pip install airbyte ``` Or during the beta, you may want to install the latest from from source with: ```bash -pip install 'git+https://www.github.com/airbytehq/airbyte.git@master#egg=airbyte-lib&subdirectory=airbyte-lib' +pip install 'git+https://github.com/airbytehq/PyAirbyte.git' ``` ## Usage @@ -23,7 +23,7 @@ Data can be extracted from sources and loaded into caches:
Try with Colab ```python -import airbyte_lib as ab +import airbyte as ab source = ab.get_source( "source-faker", @@ -38,9 +38,18 @@ for name, records in result.streams.items(): print(f"Stream {name}: {len(list(records))} records") ``` +## Quickstarts + +* [CoinAPI](https://github.com/airbytehq/quickstarts/blob/main/airbyte_lib_notebooks/AirbyteLib_CoinAPI_Demo.ipynb) +* [GA4](https://github.com/airbytehq/quickstarts/blob/main/airbyte_lib_notebooks/AirbyteLib_GA4_Demo.ipynb) +* [Shopify](https://github.com/airbytehq/quickstarts/blob/main/airbyte_lib_notebooks/PyAirbyte_Shopify_Demo.ipynb) +* [GitHub](https://github.com/airbytehq/quickstarts/blob/main/airbyte_lib_notebooks/AirbyteLib_Github_Incremental_Demo.ipynb) +* [Postgres (cache)](https://github.com/airbytehq/quickstarts/blob/main/airbyte_lib_notebooks/PyAirbyte_Postgres_Custom_Cache_Demo.ipynb) + + ## API Reference -For details on specific classes and methods, please refer to our [AirbyteLib API Reference](./reference). +For details on specific classes and methods, please refer to our [PyAirbyte API Reference](https://airbytehq.github.io/PyAirbyte/index.html). ## Architecture @@ -48,7 +57,7 @@ For details on specific classes and methods, please refer to our [AirbyteLib API ![Architecture](../../assets/docs/airbyte-lib-high-level-architecture.svg) -airbyte-lib is a python library that can be run in any context that supports Python >=3.9. It contains the following main components: +PyAirbyte is a python library that can be run in any context that supports Python >=3.9. It contains the following main components: * **Source**: A source object is using a Python connector and includes a configuration object. The configuration object is a dictionary that contains the configuration of the connector, like authentication or connection modalities. The source object is used to read data from the connector. * **Cache**: Data can be read directly from the source object. However, it is recommended to use a cache object to store the data. The cache object allows to temporarily store records from the source in a SQL database like a local DuckDB file or a Postgres or Snowflake instance. * **Result**: An object holding the records from a read operation on a source. It allows quick access to the records of each synced stream via the used cache object. Data can be accessed as a list of records, a Pandas DataFrame or via SQLAlchemy queries. diff --git a/docs/using-airbyte/airbyte-lib/reference.mdx b/docs/using-airbyte/airbyte-lib/reference.mdx deleted file mode 100644 index 07d0dd7fdf33..000000000000 --- a/docs/using-airbyte/airbyte-lib/reference.mdx +++ /dev/null @@ -1,15 +0,0 @@ -import AirbyteLibDefinitions from '@site/src/components/AirbyteLibDefinitions'; - -# airbyte-lib reference - -This page contains the reference documentation for the airbyte-lib library. - -## Main `airbyte_lib` module - - - -## Caches `airbyte_lib.caches` - -The following cache implementations are available - - \ No newline at end of file diff --git a/docusaurus/redirects.yml b/docusaurus/redirects.yml index 69b847a30dff..b5f2bf9e8afc 100644 --- a/docusaurus/redirects.yml +++ b/docusaurus/redirects.yml @@ -93,3 +93,6 @@ - /enterprise-setup/self-managed/sso - /enterprise-setup/sso to: /access-management/sso +- from: + - /pyairbyte + to: /using-airbyte/airbyte-lib/getting-started diff --git a/docusaurus/static/img/pyairbyte-logo-dark.png b/docusaurus/static/img/pyairbyte-logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ff38a150b6eb6ecf529e8ed25c50bbc8c6e3bbae GIT binary patch literal 8055 zcmV--ABfUZZ|Mv9^edSXHUer!#n}<6O6e&C)R>}01V8YTf`IK zeFC%*@ z!?y|LaBd8A&`7?r4d}GnrVEOqD9XY!mqw91!o?rzcXiKEQ50n{sI5_?P$_z22PG!YL<3*M*56;4Jx~-yQRbRj z8b$ODAEI}-5B2m8$Dv-MqA1FolR(Y*>rd_}8pJltmq8>_W8p1&xbd@L6-7~$DAdYR z{Odz^5H*>`^b7Sz7V?)#19lD$%yUo_MN#I8+8D)B4WjW1H63f<9sbnCucP6xCS|nZ zw-ovw-X=cg`%?EW)i5fGqRbt&Fp8xZMB_cc=eVzThz76&0px~q+cGQt-r2^5YBm?e4|>bilQiUz)X!|UW2#~ zAw)8U!{jPDzvL=9A!t^rqA1FoFf*f=dtx6T1OrFTz=J9c4PNgKUhgjuk`;^Bd+^-c z0Yy<1rPj=>B!kKqAOH-tJ|hEDwdaNBYoo_^CvP_;!@&mboBjfdq9{tOnTb)PeMA6x zSpJMh|xp6V+@&CJtP6h%=cQ>jrzgRmp5|HD1R zJv4}68LE-71|E_3CwUBpU!Ugnkcy%xO3kR$D3U>tj3-YF_Yhl9Q>YY#vS0x~QWCP3 zSWs_KQ52@MZJqT+2(9k@h zG6BDzr&E7us`=BWd72!=#OS+YqMv3I1RD2gIx z1tLNv7*42MgI?k@C6lA=E0LTE7;C4o#+K}eJ_!xRDH9Mv~P$&R-o`T_Pc)kr# z6h%>LK@_9tlWPJR2V*!$T2rW)X7hdvR{$|fLb@22@8b6( z(`dZ0*cA{fL01H%|pGJ%hkJdYF> z4~i6Q;@7UtvbW7!TOY^>q&K%yP=HRhoB97=#$M{g5K1{bxuh*K0O$tYGC&LrtJ_E;9}}+6hk;WJM5mE{o1mQJ}kWQl&Xr;XT@cb zu@(r%@B}RKMMSC4`(|B2TMN%eT-Uh+`{d+I)nJsxCfF$EwSqfP9%=I4r1 z4q-FFLP1cUId9M;Ym(#vO{kplv5V7Z2{*wev&j?A>qU!*7&VK2L38qE=i2qgH;Hq1 z>FXLUZjMi0e{*{JPYs(Y3s107ELwswhN&Kw5h&jzcD&JUNcMMxYCDo-AS2X!oi~n; z50B6y>~Y3YaXKs@e{OD(u}`OuG+i`Gw6FIH7+hS~Xhrn2NA%m-uO0fTtKO-i#30Bh z#wx)uc6x#ap7-Ct1SglLc&%R@liD>|Nuq+_oPM|MD}Z*lGB0+wgs zeaJHQ2CO%RiM4Ic_&ni8QIrx1GK$8*ONhhN!enWCDKxY%sZZj6qapksH0HDqnhS}u zLr;=(=KT><;Ir^Xk-+^ZRt9U5WD8ZyPYE{GF|%=#l{S4_xv_G@T|_MMKCGh50{3I&RVA#+>Edr-RVx01Ba6GkuSBkZ`j|bz)b^ zlZpJ?fzPoE6@lkXul#tvsITw5bM^ip%D6{FMv+2~lHz$PH)uaMtw%rkOi!){^$@+q z)`df5bUJ`SsFxS^+_~u) z*?GcE3kve*=JvKV+0^r`W{ru-H#AXQUS?B6#;dE1!(n6NAKMo_|B;#;Uwr!GdYZSk zXpxGq33L+Yo>3AIlmMNx*Mkjb-9zW>CjAP}`^A{`=GHl`K#rU-?~F+f2VVUoxUZ+l z8r?E$Kc(j#H{LO8tyhfwaeaO3_i5*W5+FeVmu0lgwlREv5QBS!-YW=fa?Uo2KDoxq zK6oxSD6}V+8!--RiG_(Dax$1+ktVcvBNH@m&m`eZkrz!1hPLT|GLdo-Yl?s%P3Y>dMRg|F|K>{XPQ`iC-^B}_yK=e zR^1*Y$7C*h$vSW1J&TdY;AUt$a3hnD*jcDxHs(3uhF+`Yt$XjO*XA_iG@#)cg|;5P zy>*|A;Rne%hae~6U{Y_;Yu8rTS=VKi*GRgsIM+CYnv*Y-io8!miUxK6!enoA{o#qQ zj3Q-jN=q=%YkF|?XEXw=?8BTjjxH&Bpu6H4LMG#MQ%6At92ZKWn_3c4N zC8rD<6x;W@_~8L`=W&m2;v`35)Pv{d4#*7dbo!yqHg~vG$Y9j#v&iHh)=kdX;mK|m z6AQjWJOeXfV&Nv(;6aYY9m9vy94{I|!Ur)FZen7SY^`q)#UdcVi7yz1+U1Cz%Ma{Y zqYNW0>VQY#MV(|Jme@vZ^BJf$8ZJ!VOBYIf%tqg99No)xs!{YM7{cV5QC<)kFrl~T z_vogDQHg^WW;diy;)L@);EoLuGFUb*@zPjkXxWTZ+pp4Fq=|)-+(L|-SkivK!xR`` z=yc-bWSr%OxYj=P6IA90XDBBi1tGP~+8$vT{r${Ms4KXr6D-8Kbrp3dgXnDbzC`bE z94R$9ALTJlG>U%0mzH4Q%66O=B=#05jB4R6$1o21BvJ`T5#yM9aqJJBRLEf2yu@bn z-cy|TS%%7heK+d&ReFnMOe|&Y>rjRzH-wrn#4qZ_^w0H}$JMu=BO1ox{atGtE#{+x z7dDjX49o?FVahI6jWzZ&0!sd2>b$C7)q!6VfY?_0BAAU?2Gn$#?~oP@(82U<;n%Z;Q=!_ z1&zrg^!{XSviaNtkwt#}DR=xpXn;FBM92WYxZX}}z~{K(4css$>3%iVWgC|lSsJq1 z!%1V0F{YK6jAOX`#4@Rd?5hV*7Nlc_uE>C&jxpeZ?knRA>o62TU2ooJ74qi^H?8?q zU@=_-?%C?~MtjtAAi?;PlCvg#uSjd3U4xbOs5&;^G&{*!_~P;xTm3Np{@^*#f)6L& z=d5G&@1Zs@K~IP6U5@&kWf=8nfca{{=?t$4dje(`@6EBr`xv#GcrWIky%sR>3naYe z-%j6jzB(3(KYYx#oo{e12+uoT^X?a)BaPzEJ8s)raq`F$?$}jy;d>y1_6xaVbD@D9 z5a0x1%}^l&iBYc+Ya_GuM#^0n+EbR}%pNCpxxk!3D^d@l_XTbf38+aLj z^uZRT#P>s}oXHQp6n_o143SOY@Y?m{(IkUjei?!3W;VHdcJ{gplh3(>#t|1~_APU= zT^m*!;x6h2VQ_9T431|-2gcoVXJeFsnzy!CMzQCTS4G|zUjoIPH+-Y(34J~Dd#8=Y z@$m9fuZ4?5?t}nCQY%!^`?7##@|k;3TnX3+Jnbv64xMJ#T!P$t0owHZoUYg z=3zlu@`zCRMSOe*&v37=%N{RGevx*;2=Q_y$6p>~tMsds9)=Q4EU(+6{^ApCEHiUe z8af@o522PO5?%#lC@S9rowP4J1zMmqoA>r`vY9&9H2MYg?W>Q)J^GGg2nghhy3V-2 zOTzUITrI=tmRCk}ZW^vj349QMwLZ$S!5K?J_FovqpyU)u*byh6x+TBF?1CZna+d`P zX&j%v*@ZyJpv+=o!P&br_HTj&8=Rol)|)@F_G`X;piTK>y%ui^YR~wEMoc(~U6a7M ztYbL~aO=LBjA;?zjM<#_&}oZ0(O#Tul&ktx7Q709HLo=c(_7CK2H&sGMzOBRDcrF^ z*H1zN&+FsmE;^sH#!6`UGmD9(j0BrL21D>xRNorFnj~3cW=vXW#5?Ix(S#lEE#BJd z!jwg_1Cx$=Y|%xX&$7I*+rYVb3wXuRF=ityJ1-9Oetq6klqRR-$uDj0_<-b;PE7sL zX+i@djxXwhAwB-0(yt{-+KF>_(L20bRu4SC$5ukpf?ywTY=)iBT&*G8J=GcW3M$9_ z8%iMIH6!?b)Gv$fEmD}Ts2pJ(;68`yFyDDkQJkD23=4*ocu*}PcWgyot|;8+79ecu z6FZ!f6-rb6qRW2w^=A0kQME*6QPf+M>;opQF@BTZ@r(YeWRN&e=bA;Fuq(ed4BvO5 z1T2`}0m8hTqTb>n=$!VGkSYj?ig5iz8?iDA8Z1ePL`aE;BsnESfAm1;g~k#xs5NNR z$h(7@Qiq9!q~UBPQ{t$Sx+mQ9pd1l@3C<+7SR_ambrhl>2n$H=xw`6{)|rHoQ-B*5 zL=Vv=@Bj@WJCmuB5|4=bqq!Ho0|F#M21+p`VW{FH;_ zgAz!<{b~BB@ntlUEr5%}?hO84h8$rXxN!q&8Nr}EMZ+0L-W7U?cO(WesLO_hXOZ=wpbffWV3N_Xr?Q+J_@ohkIje3dIGpmV3TB0*E zoZUtv@ML~P!po=VUh75Dd&tqsb&SObcTty_jJgG}#2YAja(sL!OOl%b`1+93HPI;I zbJ>9#P?^9(0+Fa;iAOhjiN}KJo4OI5FzO073`G-*Ai?Hn+{7Z;lg#Nx_~H`WymnzJ z(2Tm@4A<;%#&X(Rakl^xBbbva)HzL(=^pbq46jag?ebH33r4X55eU&Am4qEh zf3#P>5)VzTnIT+nktP;yYpY594uuIeuTDK#9hz%V-=%!H0gX1mACYI3x z%6$*Ru#FtvPf_j-YggLbv5qS+y+lyL3NEDB5iNS(o6W5QP6?1lpw=Tw7%TC-lR!ho z6reW`(;?w=E84(M%HHSi-P(o8-j2KG(v701#Dk#ZmxRB9 z6_fr#A+B&~=DXL_Z3tMd+dAkAA_AEt>-4<=O*WE)HM zRm-X=EUN1|fT`F+Of)jn$Q-|Q9NzE0tmDFjdoFt4s7bobvbXT1-AFG?@8zfvda2>l z(Bzt^T{b|L{1V{hYI04D;3h3hW8%c(sBtM%&LO_GC&{F3at8VpeY)M!gqyEOY0_-o zx_4v%BT9)+{^(=jdurl~e@{U|fZnJ?jA8<>$|}Qf&itEwpL-*deW2^7YrxmAe~(!& zbGJeH2`4A7Muw{U0{{1(aT@}YhmYsl@voIJ@9;NANzzwFvNl^YeUb6+roV4yV^j#e zRHL|zT{h_E2cT2B;V2Wbgfg2@ zZ>{j6uEhC>8e8MFh#FSspSw||O6^IHTfM&0y7**q-`k}iIahx_6VUiw{XH8pu+8Ru zG}x~{zh9+=PrVoCA}7B<Mj$?XR!@#eXhJF^aMEN2$w3fEW6JJ2ueEy$cJD@!c-wlNb{Vb=3etc)cp!N$HB- zIjadbQ7}i>t~bOb9>et8tH~o!G48i(*H-pJt|b&&kfMY2sA`YVfO~#?{Qo|xQ;JcH zotzTVWkYg&W8p0bSQdTLx^xo=A=F!(II-ZKHt=~>rS7C?MW5?vE+aJIMw;XguU${> zmX*XLUera>Ih{pVlMG{KlRMQIW7F;Tdj0kD)>&brSi2I8kS-e$OFWd>QRc+rg_uDS zI*n7CI1Wk8BII&+u!PW}$GYThS*1I^z#Z(9lhZd3%FOERhw%AEA!Z|CAJ#O<-6}ms z`W)gS;|_XoQNp)*uh>00$8h8GLPjw(`K8Si7Z2*P;o!NT#A8iMFcueS7;4hQB2KW0 zRGT;sdCg*ZvRU&4wJW06iu!~W^&08*CXeRy^q-NkdAWI%<|uX}VKR)gn7}6;&G-&O ziwyGMtZUpZ@w{C!hO5_-+b3tgjx0|qRFWZWz8j)H8nXl=vG6$N@s&Ejo>(SIaycJ0 z=NTQ`vwH`#02hRGk-;SHU&c;9fXN!&sbi|{%3-04&%HBk*wsleU%0gY+}zsE96Utt zVUtnXLX+xq)3AqwJ*XH68wppE43kGucGlOo_npgjab@+xv=Rz@O^=+luS^oI_%%3h znr`o2e$2Mfk@=CzXE@~>xkq?}@9R7C06W88;mF58Ai4hNd&y&50=FfF`ncEk0R-Uj zA90Ot?Bmy&X7hdvZ* z{XU~BCQW3P?WuBu+kuh^+Ec6|`6XtTjldF*!l~9ub;vrDyN*hqDRtq}WbEwVvUE=KWI1xl{TL!vEMU~pn#FRFB6QR)O~c5=o|k|R{Y5qpYB zzg8<{4Mq%6cT{fg%sFiu4%IwjJMVVXJ0uj}h{VWUO@M-&nFG*;jf!W0G8^%J4 z;l)4U{>|?$@y7B9eJ3e>iOo!nB9%x;#^+(v zHg|k}{FFOB51Y0@nL8vCONb*qy@pnO) zJERkfCfF!-;j+Oj9|DyltcsZ##U8grg4A&mcpx=c#=!w^ARgbr6E%qQi%u-cyu#fF zS2@D!n3+*Lcy8`ee?o&RcYMdc)J8SFVdx?K9ryUC2ctNS&OH7TfBb)_YRx>O6N@sB zs2pKEDblA~QD#owHJ#PlQyU2@bz;z Date: Sun, 25 Feb 2024 12:53:39 -0500 Subject: [PATCH 68/74] Source S3: run incremental syncs with concurrency (#34895) --- .../connectors/source-s3/metadata.yaml | 2 +- .../connectors/source-s3/poetry.lock | 116 +++++++++--------- .../connectors/source-s3/pyproject.toml | 2 +- .../source-s3/source_s3/v4/source.py | 2 + .../source-s3/source_s3/v4/stream_reader.py | 31 +++-- .../unit_tests/v4/test_stream_reader.py | 84 ++++++++----- docs/integrations/sources/s3.md | 1 + 7 files changed, 129 insertions(+), 109 deletions(-) diff --git a/airbyte-integrations/connectors/source-s3/metadata.yaml b/airbyte-integrations/connectors/source-s3/metadata.yaml index 055abf46d9f2..2b3b204f87be 100644 --- a/airbyte-integrations/connectors/source-s3/metadata.yaml +++ b/airbyte-integrations/connectors/source-s3/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: file connectorType: source definitionId: 69589781-7828-43c5-9f63-8925b1c1ccc2 - dockerImageTag: 4.5.6 + dockerImageTag: 4.5.7 dockerRepository: airbyte/source-s3 documentationUrl: https://docs.airbyte.com/integrations/sources/s3 githubIssueLabel: source-s3 diff --git a/airbyte-integrations/connectors/source-s3/poetry.lock b/airbyte-integrations/connectors/source-s3/poetry.lock index 168bad963884..b8b2e27ae350 100644 --- a/airbyte-integrations/connectors/source-s3/poetry.lock +++ b/airbyte-integrations/connectors/source-s3/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "airbyte-cdk" -version = "0.63.1" +version = "0.67.0" description = "A framework for writing Airbyte Connectors." optional = false python-versions = ">=3.8" files = [ - {file = "airbyte-cdk-0.63.1.tar.gz", hash = "sha256:e1442e2219d8620ee1716c6830b17de51190cf81061381e42c7a362cc5a63501"}, - {file = "airbyte_cdk-0.63.1-py3-none-any.whl", hash = "sha256:d699012515939c8bae82d7f83a8e6d66306ef3da6904def4c8a90e0d371e09e2"}, + {file = "airbyte-cdk-0.67.0.tar.gz", hash = "sha256:cbbff1b3895c89313764a721870bb293a396c74bad8dd6e5c36a0c3b0a2f6a10"}, + {file = "airbyte_cdk-0.67.0-py3-none-any.whl", hash = "sha256:2082c859536a2450c03b89dba1bbdab21bad314fbf5ef6d2e86fefc4ba935373"}, ] [package.dependencies] @@ -140,17 +140,17 @@ lxml = ["lxml"] [[package]] name = "boto3" -version = "1.34.43" +version = "1.34.48" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.8" files = [ - {file = "boto3-1.34.43-py3-none-any.whl", hash = "sha256:179cdcff2dee116ff0bbe10c21a374fff8ae0d9ea3842bd8dd2c9f69e8185d91"}, - {file = "boto3-1.34.43.tar.gz", hash = "sha256:ed646f600b76939d54fa1ff868415793551a5a08b9de0a09696b46d116da7da5"}, + {file = "boto3-1.34.48-py3-none-any.whl", hash = "sha256:adc785ff05aec9fc93f82d507420b320203cd4fd011c67eb369b3aa2b5aeb298"}, + {file = "boto3-1.34.48.tar.gz", hash = "sha256:f9873c3f03de546d7297475c6acd771840c385521caadb8c121a1ac38bc59cd4"}, ] [package.dependencies] -botocore = ">=1.34.43,<1.35.0" +botocore = ">=1.34.48,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -159,13 +159,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.43" +version = "1.34.48" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.8" files = [ - {file = "botocore-1.34.43-py3-none-any.whl", hash = "sha256:ab7d8046a8c3326ecf3d9f9884e79aa77fed864416ed8af52b9e22ab055acf4e"}, - {file = "botocore-1.34.43.tar.gz", hash = "sha256:00dea9fd602dc97420318d373079bdfcc8da34501aaa908ab98b477526bdefec"}, + {file = "botocore-1.34.48-py3-none-any.whl", hash = "sha256:f3e1c84fa75fd6921dfbfb4b2f803bcc424b9b866982fe80e08edbd26ca9861c"}, + {file = "botocore-1.34.48.tar.gz", hash = "sha256:eabdde36309274b76bb79ae9bdfa10c1fd91a2c9b3343cfa15b8a91f8e1ec224"}, ] [package.dependencies] @@ -438,43 +438,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.3" +version = "42.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, - {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, - {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, - {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, - {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, - {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, - {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b"}, + {file = "cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925"}, + {file = "cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923"}, + {file = "cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0"}, + {file = "cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129"}, + {file = "cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660"}, + {file = "cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb"}, ] [package.dependencies] @@ -2070,13 +2070,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-cache" -version = "1.1.1" +version = "1.2.0" description = "A persistent cache for python requests" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8" files = [ - {file = "requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90"}, - {file = "requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60"}, + {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"}, + {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"}, ] [package.dependencies] @@ -2088,15 +2088,15 @@ url-normalize = ">=1.4" urllib3 = ">=1.25.5" [package.extras] -all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] bson = ["bson (>=0.5)"] -docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] json = ["ujson (>=5.4)"] mongodb = ["pymongo (>=3)"] redis = ["redis (>=3)"] security = ["itsdangerous (>=2.0)"] -yaml = ["pyyaml (>=5.4)"] +yaml = ["pyyaml (>=6.0.1)"] [[package]] name = "requests-mock" @@ -2155,19 +2155,19 @@ crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -2550,13 +2550,13 @@ files = [ [[package]] name = "xlsxwriter" -version = "3.1.9" +version = "3.2.0" description = "A Python module for creating Excel XLSX files." optional = false python-versions = ">=3.6" files = [ - {file = "XlsxWriter-3.1.9-py3-none-any.whl", hash = "sha256:b61c1a0c786f82644936c0936ec96ee96cd3afb9440094232f7faef9b38689f0"}, - {file = "XlsxWriter-3.1.9.tar.gz", hash = "sha256:de810bf328c6a4550f4ffd6b0b34972aeb7ffcf40f3d285a0413734f9b63a929"}, + {file = "XlsxWriter-3.2.0-py3-none-any.whl", hash = "sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e"}, + {file = "XlsxWriter-3.2.0.tar.gz", hash = "sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c"}, ] [[package]] diff --git a/airbyte-integrations/connectors/source-s3/pyproject.toml b/airbyte-integrations/connectors/source-s3/pyproject.toml index b19e21b9612d..3127d3b94c76 100644 --- a/airbyte-integrations/connectors/source-s3/pyproject.toml +++ b/airbyte-integrations/connectors/source-s3/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "4.5.6" +version = "4.5.7" name = "source-s3" description = "Source implementation for S3." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-s3/source_s3/v4/source.py b/airbyte-integrations/connectors/source-s3/source_s3/v4/source.py index 30eff74f7694..22a801597aaa 100644 --- a/airbyte-integrations/connectors/source-s3/source_s3/v4/source.py +++ b/airbyte-integrations/connectors/source-s3/source_s3/v4/source.py @@ -21,6 +21,8 @@ class SourceS3(FileBasedSource): + _concurrency_level = DEFAULT_CONCURRENCY + @classmethod def read_config(cls, config_path: str) -> Mapping[str, Any]: """ diff --git a/airbyte-integrations/connectors/source-s3/source_s3/v4/stream_reader.py b/airbyte-integrations/connectors/source-s3/source_s3/v4/stream_reader.py index 411142ef71cc..c3e415df7b25 100644 --- a/airbyte-integrations/connectors/source-s3/source_s3/v4/stream_reader.py +++ b/airbyte-integrations/connectors/source-s3/source_s3/v4/stream_reader.py @@ -30,7 +30,6 @@ class SourceS3StreamReader(AbstractFileBasedStreamReader): def __init__(self): super().__init__() - self._s3_client = None @property def config(self) -> Config: @@ -56,24 +55,24 @@ def s3_client(self) -> BaseClient: # We shouldn't hit this; config should always get set before attempting to # list or read files. raise ValueError("Source config is missing; cannot create the S3 client.") - if self._s3_client is None: - client_kv_args = _get_s3_compatible_client_args(self.config) if self.config.endpoint else {} - # Set the region_name if it's provided in the config - if self.config.region_name: - client_kv_args["region_name"] = self.config.region_name + client_kv_args = _get_s3_compatible_client_args(self.config) if self.config.endpoint else {} - if self.config.role_arn: - self._s3_client = self._get_iam_s3_client(client_kv_args) - else: - self._s3_client = boto3.client( - "s3", - aws_access_key_id=self.config.aws_access_key_id, - aws_secret_access_key=self.config.aws_secret_access_key, - **client_kv_args, - ) + # Set the region_name if it's provided in the config + if self.config.region_name: + client_kv_args["region_name"] = self.config.region_name + + if self.config.role_arn: + _s3_client = self._get_iam_s3_client(client_kv_args) + else: + _s3_client = boto3.client( + "s3", + aws_access_key_id=self.config.aws_access_key_id, + aws_secret_access_key=self.config.aws_secret_access_key, + **client_kv_args, + ) - return self._s3_client + return _s3_client def _get_iam_s3_client(self, client_kv_args: dict) -> BaseClient: """ diff --git a/airbyte-integrations/connectors/source-s3/unit_tests/v4/test_stream_reader.py b/airbyte-integrations/connectors/source-s3/unit_tests/v4/test_stream_reader.py index 01ad2d926380..948021fd5bb0 100644 --- a/airbyte-integrations/connectors/source-s3/unit_tests/v4/test_stream_reader.py +++ b/airbyte-integrations/connectors/source-s3/unit_tests/v4/test_stream_reader.py @@ -8,7 +8,7 @@ from datetime import datetime, timedelta from itertools import product from typing import Any, Dict, List, Optional, Set -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest from airbyte_cdk.sources.file_based.config.abstract_file_based_spec import AbstractFileBasedSpec @@ -16,7 +16,7 @@ from airbyte_cdk.sources.file_based.file_based_stream_reader import FileReadMode from airbyte_cdk.sources.file_based.remote_file import RemoteFile from botocore.stub import Stubber -from moto import mock_sts +from moto import mock_s3, mock_sts from pydantic import AnyUrl from source_s3.v4.config import Config from source_s3.v4.stream_reader import SourceS3StreamReader @@ -124,10 +124,51 @@ def test_get_matching_files( except Exception as exc: raise exc - stub = set_stub(reader, mocked_response, multiple_pages) - files = list(reader.get_matching_files(globs, None, logger)) - stub.deactivate() - assert set(f.uri for f in files) == expected_uris + with patch.object(SourceS3StreamReader, 's3_client', new_callable=MagicMock) as mock_s3_client: + _setup_mock_s3_client(mock_s3_client, mocked_response, multiple_pages) + files = list(reader.get_matching_files(globs, None, logger)) + assert set(f.uri for f in files) == expected_uris + + +def _setup_mock_s3_client(mock_s3_client, mocked_response, multiple_pages): + responses = [] + if multiple_pages and len(mocked_response) > 1: + # Split the mocked_response for pagination simulation + first_half = mocked_response[:len(mocked_response) // 2] + second_half = mocked_response[len(mocked_response) // 2:] + + responses.append({ + "IsTruncated": True, + "Contents": first_half, + "KeyCount": len(first_half), + "NextContinuationToken": "token", + }) + + responses.append({ + "IsTruncated": False, + "Contents": second_half, + "KeyCount": len(second_half), + }) + else: + responses.append({ + "IsTruncated": False, + "Contents": mocked_response, + "KeyCount": len(mocked_response), + }) + + def list_objects_v2_side_effect(Bucket, Prefix=None, ContinuationToken=None, **kwargs): + if ContinuationToken == "token": + return responses[1] + return responses[0] + + mock_s3_client.list_objects_v2 = MagicMock(side_effect=list_objects_v2_side_effect) + + +def _split_mocked_response(mocked_response, multiple_pages): + if not multiple_pages: + return mocked_response, [] + split_index = len(mocked_response) // 2 + return mocked_response[:split_index], mocked_response[split_index:] @patch("boto3.client") @@ -196,9 +237,9 @@ def test_open_file_calls_any_open_with_the_right_encoding(smart_open_mock): with reader.open_file(RemoteFile(uri="", last_modified=datetime.now()), FileReadMode.READ, encoding, logger) as fp: fp.read() - smart_open_mock.assert_called_once_with( - "s3://test/", transport_params={"client": reader.s3_client}, mode=FileReadMode.READ.value, encoding=encoding - ) + assert smart_open_mock.call_args.args == ("s3://test/",) + assert smart_open_mock.call_args.kwargs["mode"] == FileReadMode.READ.value + assert smart_open_mock.call_args.kwargs["encoding"] == encoding def test_get_s3_client_without_config_raises_exception(): @@ -218,29 +259,6 @@ def documentation_url(cls) -> AnyUrl: stream_reader.config = other_config -def set_stub(reader: SourceS3StreamReader, contents: List[Dict[str, Any]], multiple_pages: bool) -> Stubber: - s3_stub = Stubber(reader.s3_client) - split_contents_idx = int(len(contents) / 2) if multiple_pages else -1 - page1, page2 = contents[:split_contents_idx], contents[split_contents_idx:] - resp = { - "KeyCount": len(page1), - "Contents": page1, - } - if page2: - resp["NextContinuationToken"] = "token" - s3_stub.add_response("list_objects_v2", resp) - if page2: - s3_stub.add_response( - "list_objects_v2", - { - "KeyCount": len(page2), - "Contents": page2, - }, - ) - s3_stub.activate() - return s3_stub - - @mock_sts @patch("source_s3.v4.stream_reader.boto3.client") def test_get_iam_s3_client(boto3_client_mock): @@ -303,4 +321,4 @@ def test_filter_file_by_start_date(start_date: datetime, last_modified_date: dat start_date=start_date.strftime("%Y-%m-%dT%H:%M:%SZ") ) - assert expected_result == reader.is_modified_after_start_date(last_modified_date) \ No newline at end of file + assert expected_result == reader.is_modified_after_start_date(last_modified_date) diff --git a/docs/integrations/sources/s3.md b/docs/integrations/sources/s3.md index 0fa3b9dbc96c..1586348a10d8 100644 --- a/docs/integrations/sources/s3.md +++ b/docs/integrations/sources/s3.md @@ -264,6 +264,7 @@ To perform the text extraction from PDF and Docx files, the connector uses the [ | Version | Date | Pull Request | Subject | |:--------|:-----------|:----------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------| +| 4.5.7 | 2024-02-23 | [34895](https://github.com/airbytehq/airbyte/pull/34895) | Run incremental syncs with concurrency | | 4.5.6 | 2024-02-21 | [35246](https://github.com/airbytehq/airbyte/pull/35246) | Fixes bug that occurred when creating CSV streams with tab delimiter. | | 4.5.5 | 2024-02-18 | [35392](https://github.com/airbytehq/airbyte/pull/35392) | Add support filtering by start date | | 4.5.4 | 2024-02-15 | [35055](https://github.com/airbytehq/airbyte/pull/35055) | Temporarily revert concurrency | From 5139a294be473f103239ff6fe478491e0e7ad4b5 Mon Sep 17 00:00:00 2001 From: Anton Karpets Date: Mon, 26 Feb 2024 15:52:02 +0200 Subject: [PATCH 69/74] =?UTF-8?q?=F0=9F=8F=A5Source=20GitHub:=20fix=20vers?= =?UTF-8?q?ion=20in=20pyproject.toml=20(#35625)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airbyte-integrations/connectors/source-github/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-github/pyproject.toml b/airbyte-integrations/connectors/source-github/pyproject.toml index 54b0e89c3bef..085b9c828c18 100644 --- a/airbyte-integrations/connectors/source-github/pyproject.toml +++ b/airbyte-integrations/connectors/source-github/pyproject.toml @@ -3,9 +3,9 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "1.6.2" +version = "1.6.3" name = "source-github" -description = "Source implementation for Github." +description = "Source implementation for GitHub." authors = [ "Airbyte ",] license = "MIT" readme = "README.md" From 7c11ea74a5a02f5f5fb529dbea8588c38e8491b6 Mon Sep 17 00:00:00 2001 From: Anton Karpets Date: Mon, 26 Feb 2024 15:53:38 +0200 Subject: [PATCH 70/74] =?UTF-8?q?=F0=9F=8F=A5Source=20Klaviyo:=20fix=20ver?= =?UTF-8?q?sion=20in=20pyproject.toml=20(#35626)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration_tests/expected_records.jsonl | 54 +++++++++---------- .../connectors/source-klaviyo/pyproject.toml | 2 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/airbyte-integrations/connectors/source-klaviyo/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-klaviyo/integration_tests/expected_records.jsonl index 24cc25ea2160..563ff612a99b 100644 --- a/airbyte-integrations/connectors/source-klaviyo/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-klaviyo/integration_tests/expected_records.jsonl @@ -17,33 +17,33 @@ {"stream": "lists", "data": {"type": "list", "id": "RnsiHB", "attributes": {"name": "Newsletter", "created": "2021-03-31T10:50:36+00:00", "updated": "2021-03-31T10:50:36+00:00", "opt_in_process": "double_opt_in"}, "relationships": {"profiles": {"links": {"self": "https://a.klaviyo.com/api/lists/RnsiHB/relationships/profiles/", "related": "https://a.klaviyo.com/api/lists/RnsiHB/profiles/"}}, "tags": {"links": {"self": "https://a.klaviyo.com/api/lists/RnsiHB/relationships/tags/", "related": "https://a.klaviyo.com/api/lists/RnsiHB/tags/"}}}, "links": {"self": "https://a.klaviyo.com/api/lists/RnsiHB/"}, "updated": "2021-03-31T10:50:36+00:00"}, "emitted_at": 1707338396897} {"stream": "lists", "data": {"type": "list", "id": "RwKPyg", "attributes": {"name": "Test5", "created": "2021-11-16T14:24:26+00:00", "updated": "2021-11-16T14:24:26+00:00", "opt_in_process": "double_opt_in"}, "relationships": {"profiles": {"links": {"self": "https://a.klaviyo.com/api/lists/RwKPyg/relationships/profiles/", "related": "https://a.klaviyo.com/api/lists/RwKPyg/profiles/"}}, "tags": {"links": {"self": "https://a.klaviyo.com/api/lists/RwKPyg/relationships/tags/", "related": "https://a.klaviyo.com/api/lists/RwKPyg/tags/"}}}, "links": {"self": "https://a.klaviyo.com/api/lists/RwKPyg/"}, "updated": "2021-11-16T14:24:26+00:00"}, "emitted_at": 1707338396898} {"stream": "email_templates", "data": {"type": "template", "id": "RdbN2P", "attributes": {"name": "Newsletter #1 (Images & Text)", "editor_type": "SYSTEM_DRAGGABLE", "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n
\n\n\n\n\n\n\n
\n\n
\n\n\n\n\n\n\n
\n\n
\n\n\n\n\n\n\n
\n\n
\n\n
\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n
\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n

\n

\n\n
\n
\n
\n
\n\n
\n\n\n
\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n

This template starts with images.

\n
\n
\n
\n
\n\n
\n\n\n
\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n
\n\n
\n
\n
\n
\n
\n
\n\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n
\n\n
\n
\n
\n
\n
\n
\n\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n
\n\n
\n
\n
\n
\n
\n
\n\n
\n\n\n
\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n

Everyone loves pictures. They're more engaging that text by itself and the images in this template will neatly stack on mobile devices for the best viewing experience.

\n

Use the text area below to add additional content or add more images to create a larger image gallery. You can drag blocks from the left sidebar to add content to your template. You can customize this colors, fonts and styling of this template to match your brand by clicking the \"Styles\" button to the left.

\n

Happy emailing!

\n

The Klaviyo Team

\n
\n
\n
\n
\n\n
\n\n\n
\n\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n
\n\n
\n\n
\n\n\"Facebook\"\n\n
\n\n
\n
\n\n
\n\n\"Twitter\"\n\n
\n\n
\n
\n\n
\n\n\"LinkedIn\"\n\n
\n\n
\n\n
\n
\n
\n
\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n
No longer want to receive these emails? {% unsubscribe %}.
{{ organization.name }} {{ organization.full_address }}
\n
\n
\n
\n
\n\n
\n\n
\n\n
\n
\n\n
\n
\n\n
\n\n
\n\n\n\n\n\n\n
\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n
\n\n\"Powered\n\n
\n
\n
\n\n
\n
\n\n
\n
\n\n", "text": null, "created": "2021-03-31T10:50:37+00:00", "updated": "2022-05-31T06:36:45+00:00"}, "links": {"self": "https://a.klaviyo.com/api/templates/RdbN2P/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698938827838} -{"stream": "metrics", "data": {"type": "metric", "id": "RUQ6YQ", "attributes": {"name": "Active on Site", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "7FtS4J", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RUQ6YQ/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412889} -{"stream": "metrics", "data": {"type": "metric", "id": "RhP4nd", "attributes": {"name": "Dropped Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RhP4nd/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412891} -{"stream": "metrics", "data": {"type": "metric", "id": "SxR9Bt", "attributes": {"name": "Clicked Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/SxR9Bt/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412891} -{"stream": "metrics", "data": {"type": "metric", "id": "THfYvj", "attributes": {"name": "Marked Email as Spam", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/THfYvj/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412891} -{"stream": "metrics", "data": {"type": "metric", "id": "VvFRZN", "attributes": {"name": "Unsubscribed", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VvFRZN/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412891} -{"stream": "metrics", "data": {"type": "metric", "id": "WKHXf4", "attributes": {"name": "Received Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/WKHXf4/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412892} -{"stream": "metrics", "data": {"type": "metric", "id": "Xi7Kwh", "attributes": {"name": "Bounced Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Xi7Kwh/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412892} -{"stream": "metrics", "data": {"type": "metric", "id": "Yy9QKx", "attributes": {"name": "Opened Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Yy9QKx/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1698943412892} -{"stream": "metrics", "data": {"type": "metric", "id": "VFFb4u", "attributes": {"name": "Clicked Email", "created": "2021-05-17T23:43:50+00:00", "updated": "2021-05-17T23:43:50+00:00", "integration": {"object": "integration", "id": "7FtS4J", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VFFb4u/"}, "updated": "2021-05-17T23:43:50+00:00"}, "emitted_at": 1698943412892} -{"stream": "metrics", "data": {"type": "metric", "id": "Tp8t7d", "attributes": {"name": "Subscribed to List", "created": "2021-11-16T15:05:22+00:00", "updated": "2021-11-16T15:05:22+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Tp8t7d/"}, "updated": "2021-11-16T15:05:22+00:00"}, "emitted_at": 1698943412893} -{"stream": "metrics", "data": {"type": "metric", "id": "R2WpFy", "attributes": {"name": "Refunded Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/R2WpFy/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412893} -{"stream": "metrics", "data": {"type": "metric", "id": "RDXsib", "attributes": {"name": "Ordered Product", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RDXsib/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412893} -{"stream": "metrics", "data": {"type": "metric", "id": "SPnhc3", "attributes": {"name": "Checkout Started", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/SPnhc3/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412893} -{"stream": "metrics", "data": {"type": "metric", "id": "TspjNE", "attributes": {"name": "Placed Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TspjNE/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412894} -{"stream": "metrics", "data": {"type": "metric", "id": "UBNaGw", "attributes": {"name": "Subscribed to Back in Stock", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/UBNaGw/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412894} -{"stream": "metrics", "data": {"type": "metric", "id": "VePdj9", "attributes": {"name": "Cancelled Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VePdj9/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412894} -{"stream": "metrics", "data": {"type": "metric", "id": "X3f6PC", "attributes": {"name": "Fulfilled Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/X3f6PC/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412894} -{"stream": "metrics", "data": {"type": "metric", "id": "YcDVHu", "attributes": {"name": "Viewed Product", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "7FtS4J", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/YcDVHu/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1698943412895} -{"stream": "metrics", "data": {"type": "metric", "id": "RcjEmN", "attributes": {"name": "Fulfilled Partial Order", "created": "2022-05-31T06:45:47+00:00", "updated": "2022-05-31T06:45:47+00:00", "integration": {"object": "integration", "id": "0eMvjm", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RcjEmN/"}, "updated": "2022-05-31T06:45:47+00:00"}, "emitted_at": 1698943412895} -{"stream": "metrics", "data": {"type": "metric", "id": "RszrqT", "attributes": {"name": "Received Automated Response SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RszrqT/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412895} -{"stream": "metrics", "data": {"type": "metric", "id": "S5Au3w", "attributes": {"name": "Failed to Deliver SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/S5Au3w/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412895} -{"stream": "metrics", "data": {"type": "metric", "id": "TS2mxZ", "attributes": {"name": "Unsubscribed from SMS Marketing", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TS2mxZ/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412896} -{"stream": "metrics", "data": {"type": "metric", "id": "TeZiVn", "attributes": {"name": "Failed to deliver Automated Response SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TeZiVn/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412896} -{"stream": "metrics", "data": {"type": "metric", "id": "VEsf4u", "attributes": {"name": "Subscribed to SMS Marketing", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VEsf4u/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412896} -{"stream": "metrics", "data": {"type": "metric", "id": "WhthF7", "attributes": {"name": "Received SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/WhthF7/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412896} -{"stream": "metrics", "data": {"type": "metric", "id": "XsS8yX", "attributes": {"name": "Sent SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/XsS8yX/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412897} -{"stream": "metrics", "data": {"type": "metric", "id": "Y5TbbA", "attributes": {"name": "Clicked SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Y5TbbA/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1698943412897} +{"stream": "metrics", "data": {"type": "metric", "id": "R2WpFy", "attributes": {"name": "Refunded Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/R2WpFy/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341952} +{"stream": "metrics", "data": {"type": "metric", "id": "RDXsib", "attributes": {"name": "Ordered Product", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RDXsib/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341953} +{"stream": "metrics", "data": {"type": "metric", "id": "RUQ6YQ", "attributes": {"name": "Active on Site", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "7FtS4J", "key": "api", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RUQ6YQ/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341953} +{"stream": "metrics", "data": {"type": "metric", "id": "RcjEmN", "attributes": {"name": "Fulfilled Partial Order", "created": "2022-05-31T06:45:47+00:00", "updated": "2022-05-31T06:45:47+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RcjEmN/"}, "updated": "2022-05-31T06:45:47+00:00"}, "emitted_at": 1708940341954} +{"stream": "metrics", "data": {"type": "metric", "id": "RhP4nd", "attributes": {"name": "Dropped Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RhP4nd/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341954} +{"stream": "metrics", "data": {"type": "metric", "id": "RszrqT", "attributes": {"name": "Received Automated Response SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/RszrqT/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341954} +{"stream": "metrics", "data": {"type": "metric", "id": "S5Au3w", "attributes": {"name": "Failed to Deliver SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/S5Au3w/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341954} +{"stream": "metrics", "data": {"type": "metric", "id": "SPnhc3", "attributes": {"name": "Checkout Started", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/SPnhc3/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341955} +{"stream": "metrics", "data": {"type": "metric", "id": "SxR9Bt", "attributes": {"name": "Clicked Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/SxR9Bt/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341955} +{"stream": "metrics", "data": {"type": "metric", "id": "THfYvj", "attributes": {"name": "Marked Email as Spam", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/THfYvj/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341955} +{"stream": "metrics", "data": {"type": "metric", "id": "TS2mxZ", "attributes": {"name": "Unsubscribed from SMS Marketing", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TS2mxZ/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341955} +{"stream": "metrics", "data": {"type": "metric", "id": "TeZiVn", "attributes": {"name": "Failed to deliver Automated Response SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TeZiVn/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341955} +{"stream": "metrics", "data": {"type": "metric", "id": "Tp8t7d", "attributes": {"name": "Subscribed to List", "created": "2021-11-16T15:05:22+00:00", "updated": "2021-11-16T15:05:22+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Tp8t7d/"}, "updated": "2021-11-16T15:05:22+00:00"}, "emitted_at": 1708940341956} +{"stream": "metrics", "data": {"type": "metric", "id": "TspjNE", "attributes": {"name": "Placed Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/TspjNE/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341956} +{"stream": "metrics", "data": {"type": "metric", "id": "UBNaGw", "attributes": {"name": "Subscribed to Back in Stock", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/UBNaGw/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341956} +{"stream": "metrics", "data": {"type": "metric", "id": "VEsf4u", "attributes": {"name": "Subscribed to SMS Marketing", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VEsf4u/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341956} +{"stream": "metrics", "data": {"type": "metric", "id": "VFFb4u", "attributes": {"name": "Clicked Email", "created": "2021-05-17T23:43:50+00:00", "updated": "2021-05-17T23:43:50+00:00", "integration": {"object": "integration", "id": "7FtS4J", "key": "api", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VFFb4u/"}, "updated": "2021-05-17T23:43:50+00:00"}, "emitted_at": 1708940341960} +{"stream": "metrics", "data": {"type": "metric", "id": "VePdj9", "attributes": {"name": "Cancelled Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VePdj9/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341960} +{"stream": "metrics", "data": {"type": "metric", "id": "VvFRZN", "attributes": {"name": "Unsubscribed", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/VvFRZN/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341961} +{"stream": "metrics", "data": {"type": "metric", "id": "WKHXf4", "attributes": {"name": "Received Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/WKHXf4/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341961} +{"stream": "metrics", "data": {"type": "metric", "id": "WhthF7", "attributes": {"name": "Received SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/WhthF7/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341961} +{"stream": "metrics", "data": {"type": "metric", "id": "X3f6PC", "attributes": {"name": "Fulfilled Order", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "0eMvjm", "key": "shopify", "name": "Shopify", "category": "eCommerce"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/X3f6PC/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341961} +{"stream": "metrics", "data": {"type": "metric", "id": "Xi7Kwh", "attributes": {"name": "Bounced Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Xi7Kwh/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341961} +{"stream": "metrics", "data": {"type": "metric", "id": "XsS8yX", "attributes": {"name": "Sent SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/XsS8yX/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341962} +{"stream": "metrics", "data": {"type": "metric", "id": "Y5TbbA", "attributes": {"name": "Clicked SMS", "created": "2022-05-31T06:52:24+00:00", "updated": "2022-05-31T06:52:24+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Y5TbbA/"}, "updated": "2022-05-31T06:52:24+00:00"}, "emitted_at": 1708940341962} +{"stream": "metrics", "data": {"type": "metric", "id": "YcDVHu", "attributes": {"name": "Viewed Product", "created": "2022-05-31T06:36:45+00:00", "updated": "2022-05-31T06:36:45+00:00", "integration": {"object": "integration", "id": "7FtS4J", "key": "api", "name": "API", "category": "API"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/YcDVHu/"}, "updated": "2022-05-31T06:36:45+00:00"}, "emitted_at": 1708940341962} +{"stream": "metrics", "data": {"type": "metric", "id": "Yy9QKx", "attributes": {"name": "Opened Email", "created": "2021-03-31T10:50:37+00:00", "updated": "2021-03-31T10:50:37+00:00", "integration": {"object": "integration", "id": "0rG4eQ", "key": "klaviyo", "name": "Klaviyo", "category": "Internal"}}, "links": {"self": "https://a.klaviyo.com/api/metrics/Yy9QKx/"}, "updated": "2021-03-31T10:50:37+00:00"}, "emitted_at": 1708940341962} {"stream": "profiles", "data": {"type": "profile", "id": "01F5VTP8THZD8CGS2AKNE63370", "attributes": {"email": "some.email.that.dont.exist@airbyte.io", "phone_number": null, "external_id": null, "anonymous_id": null, "first_name": "First Name", "last_name": "Last Name", "organization": null, "title": null, "image": null, "created": "2021-05-17T00:12:55+00:00", "updated": "2021-05-17T00:12:55+00:00", "last_event_date": null, "location": {"address1": null, "address2": null, "city": "Springfield", "country": null, "latitude": null, "longitude": null, "region": "Illinois", "zip": null, "timezone": null, "ip": null}, "properties": {}, "subscriptions": {"email": {"marketing": {"consent": "NEVER_SUBSCRIBED", "timestamp": null, "method": null, "method_detail": null, "custom_method_detail": null, "double_optin": null, "suppressions": [], "list_suppressions": []}}, "sms": null}}, "links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTP8THZD8CGS2AKNE63370/"}, "relationships": {"lists": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTP8THZD8CGS2AKNE63370/relationships/lists/", "related": "https://a.klaviyo.com/api/profiles/01F5VTP8THZD8CGS2AKNE63370/lists/"}}, "segments": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTP8THZD8CGS2AKNE63370/relationships/segments/", "related": "https://a.klaviyo.com/api/profiles/01F5VTP8THZD8CGS2AKNE63370/segments/"}}}, "updated": "2021-05-17T00:12:55+00:00"}, "emitted_at": 1679533540462} {"stream": "profiles", "data": {"type": "profile", "id": "01F5VTQ44548K2TBCG1EWPZEDN", "attributes": {"email": "some.email.that.dont.exist2@airbyte.io", "phone_number": null, "external_id": null, "anonymous_id": null, "first_name": "Strange Name1", "last_name": "Funny Name1", "organization": null, "title": null, "image": null, "created": "2021-05-17T00:13:23+00:00", "updated": "2021-05-17T00:16:44+00:00", "last_event_date": null, "location": {"address1": null, "address2": null, "city": "Springfield", "country": null, "latitude": null, "longitude": null, "region": "Illinois", "zip": null, "timezone": null, "ip": null}, "properties": {}, "subscriptions": {"email": {"marketing": {"consent": "NEVER_SUBSCRIBED", "timestamp": null, "method": null, "method_detail": null, "custom_method_detail": null, "double_optin": null, "suppressions": [], "list_suppressions": []}}, "sms": null}}, "links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTQ44548K2TBCG1EWPZEDN/"}, "relationships": {"lists": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTQ44548K2TBCG1EWPZEDN/relationships/lists/", "related": "https://a.klaviyo.com/api/profiles/01F5VTQ44548K2TBCG1EWPZEDN/lists/"}}, "segments": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTQ44548K2TBCG1EWPZEDN/relationships/segments/", "related": "https://a.klaviyo.com/api/profiles/01F5VTQ44548K2TBCG1EWPZEDN/segments/"}}}, "updated": "2021-05-17T00:16:44+00:00"}, "emitted_at": 1679533540462} {"stream": "profiles", "data": {"type": "profile", "id": "01F5VTX8KP49GGQ4BG77HZ9FRH", "attributes": {"email": "some.email.that.dont.exist3@airbyte.io", "phone_number": null, "external_id": null, "anonymous_id": null, "first_name": "Strange Name2", "last_name": "Funny Name2", "organization": null, "title": null, "image": null, "created": "2021-05-17T00:16:44+00:00", "updated": "2021-05-17T00:16:44+00:00", "last_event_date": null, "location": {"address1": null, "address2": null, "city": null, "country": null, "latitude": null, "longitude": null, "region": null, "zip": null, "timezone": null, "ip": null}, "properties": {}, "subscriptions": {"email": {"marketing": {"consent": "NEVER_SUBSCRIBED", "timestamp": null, "method": null, "method_detail": null, "custom_method_detail": null, "double_optin": null, "suppressions": [], "list_suppressions": []}}, "sms": null}}, "links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTX8KP49GGQ4BG77HZ9FRH/"}, "relationships": {"lists": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTX8KP49GGQ4BG77HZ9FRH/relationships/lists/", "related": "https://a.klaviyo.com/api/profiles/01F5VTX8KP49GGQ4BG77HZ9FRH/lists/"}}, "segments": {"links": {"self": "https://a.klaviyo.com/api/profiles/01F5VTX8KP49GGQ4BG77HZ9FRH/relationships/segments/", "related": "https://a.klaviyo.com/api/profiles/01F5VTX8KP49GGQ4BG77HZ9FRH/segments/"}}}, "updated": "2021-05-17T00:16:44+00:00"}, "emitted_at": 1679533540463} diff --git a/airbyte-integrations/connectors/source-klaviyo/pyproject.toml b/airbyte-integrations/connectors/source-klaviyo/pyproject.toml index cec0355dfd2b..c47e0677c34d 100644 --- a/airbyte-integrations/connectors/source-klaviyo/pyproject.toml +++ b/airbyte-integrations/connectors/source-klaviyo/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.1.2" +version = "2.1.3" name = "source-klaviyo" description = "Source implementation for Klaviyo." authors = [ "Airbyte ",] From 11bd88269e1048b624c9cb3904ba9b2ef0dd694a Mon Sep 17 00:00:00 2001 From: Anton Karpets Date: Mon, 26 Feb 2024 15:54:28 +0200 Subject: [PATCH 71/74] =?UTF-8?q?=F0=9F=8F=A5Source=20GitLab:=20fix=20vers?= =?UTF-8?q?ion=20in=20pyproject.toml=20(#35627)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airbyte-integrations/connectors/source-gitlab/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-gitlab/pyproject.toml b/airbyte-integrations/connectors/source-gitlab/pyproject.toml index bf22f7b57fe4..d7d58f8a0823 100644 --- a/airbyte-integrations/connectors/source-gitlab/pyproject.toml +++ b/airbyte-integrations/connectors/source-gitlab/pyproject.toml @@ -3,9 +3,9 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.1.2" +version = "3.0.0" name = "source-gitlab" -description = "Source implementation for Gitlab." +description = "Source implementation for GitLab." authors = [ "Airbyte ",] license = "MIT" readme = "README.md" From 2c912113a21b1763936662b80efcc83f5c03159d Mon Sep 17 00:00:00 2001 From: Anton Karpets Date: Mon, 26 Feb 2024 15:56:21 +0200 Subject: [PATCH 72/74] =?UTF-8?q?=F0=9F=8F=A5Source=20Hubspot:=20fix=20ver?= =?UTF-8?q?sion=20in=20pyproject.toml=20(#35629)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source-hubspot/acceptance-test-config.yml | 5 +++++ .../integration_tests/expected_records.jsonl | 16 ++++++++-------- .../connectors/source-hubspot/pyproject.toml | 2 +- docs/integrations/sources/hubspot.md | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml b/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml index ec610513aee2..4b052480a688 100644 --- a/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml @@ -185,6 +185,11 @@ acceptance_tests: bypass_reason: Hubspot time depend on current time - name: updatedAt bypass_reason: field changes too often + engagements_tasks: + - name: properties_hs_time_* + bypass_reason: Hubspot time depend on current time + - name: properties/hs_time_* + bypass_reason: Hubspot time depend on current time full_refresh: tests: - config_path: secrets/config.json diff --git a/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.jsonl index 091e59551fdb..852a890a91a5 100644 --- a/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.jsonl @@ -1,8 +1,8 @@ -{"stream": "campaigns", "data": {"id": 243851494, "lastUpdatedTime": 1675121674226, "appId": 113, "appName": "Batch", "contentId": 100523515217, "subject": "test", "name": "test", "counters": {"dropped": 1}, "lastProcessingFinishedAt": 1675121674000, "lastProcessingStartedAt": 1675121671000, "lastProcessingStateChangeAt": 1675121674000, "numIncluded": 1, "processingState": "DONE", "type": "BATCH_EMAIL", "counters_dropped": 1}, "emitted_at": 1697714185530} -{"stream": "campaigns", "data": {"id": 115429485, "lastUpdatedTime": 1615506409286, "appId": 113, "appName": "Batch", "contentId": 42931043849, "subject": "Test subj", "name": "Test subj", "counters": {"processed": 1, "deferred": 1, "mta_dropped": 1, "dropped": 3, "sent": 0}, "lastProcessingFinishedAt": 1615504712000, "lastProcessingStartedAt": 1615504687000, "lastProcessingStateChangeAt": 1615504712000, "numIncluded": 3, "processingState": "DONE", "type": "BATCH_EMAIL", "counters_processed": 1, "counters_deferred": 1, "counters_mta_dropped": 1, "counters_dropped": 3, "counters_sent": 0}, "emitted_at": 1697714185763} -{"stream": "companies", "data": {"id": "4992593519", "properties": {"about_us": null, "address": null, "address2": null, "annualrevenue": null, "city": "San Francisco", "closedate": null, "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-10T07:58:09.554000+00:00", "custom_company_property": null, "days_to_close": null, "description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "domain": "airbyte.io", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": null, "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": "2021-05-21T10:17:06.028000+00:00", "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": null, "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": null, "hs_analytics_latest_source_data_1": null, "hs_analytics_latest_source_data_2": null, "hs_analytics_latest_source_timestamp": null, "hs_analytics_num_page_views": null, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": null, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": null, "hs_analytics_source_data_1": null, "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": null, "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": null, "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": "2021-05-21T10:17:28.964000+00:00", "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": null, "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": null, "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2023-01-26T11:45:49.817000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": null, "hs_lead_status": null, "hs_merged_object_ids": null, "hs_num_blockers": null, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": null, "hs_num_decision_makers": null, "hs_num_open_deals": 1, "hs_object_id": 4992593519, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": null, "hs_predictivecontactscore_v2": null, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.5476861596107483, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": null, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": 86420513185, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": null, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-10T07:58:09.554000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": null, "is_public": false, "lifecyclestage": "opportunity", "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "name": "Airbyte test1", "notes_last_contacted": null, "notes_last_updated": null, "notes_next_activity_date": null, "num_associated_contacts": 0, "num_associated_deals": 1, "num_contacted_notes": null, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": null, "numberofemployees": 200, "phone": "+1 415-307-4864", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": null, "recent_deal_close_date": null, "state": "CA", "timezone": "America/Los_Angeles", "total_money_raised": null, "total_revenue": null, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "AirbyteHQ", "type": null, "web_technologies": "slack;segment;google_tag_manager;greenhouse;google_analytics;intercom;piwik;google_apps;hubspot;facebook_advertiser", "website": "airbyte.io", "zip": "94114"}, "createdAt": "2020-12-10T07:58:09.554Z", "updatedAt": "2023-01-26T11:45:49.817Z", "archived": false, "properties_about_us": null, "properties_address": null, "properties_address2": null, "properties_annualrevenue": null, "properties_city": "San Francisco", "properties_closedate": null, "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-10T07:58:09.554000+00:00", "properties_custom_company_property": null, "properties_days_to_close": null, "properties_description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_domain": "airbyte.io", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": null, "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": "2021-05-21T10:17:06.028000+00:00", "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": null, "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": null, "properties_hs_analytics_latest_source_data_1": null, "properties_hs_analytics_latest_source_data_2": null, "properties_hs_analytics_latest_source_timestamp": null, "properties_hs_analytics_num_page_views": null, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": null, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": null, "properties_hs_analytics_source_data_1": null, "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": null, "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": null, "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": "2021-05-21T10:17:28.964000+00:00", "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": null, "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": null, "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2023-01-26T11:45:49.817000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": null, "properties_hs_lead_status": null, "properties_hs_merged_object_ids": null, "properties_hs_num_blockers": null, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": null, "properties_hs_num_decision_makers": null, "properties_hs_num_open_deals": 1, "properties_hs_object_id": 4992593519, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": null, "properties_hs_predictivecontactscore_v2": null, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.5476861596107483, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": null, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": 86420513185, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": null, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-10T07:58:09.554000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": null, "properties_is_public": false, "properties_lifecyclestage": "opportunity", "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_name": "Airbyte test1", "properties_notes_last_contacted": null, "properties_notes_last_updated": null, "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 0, "properties_num_associated_deals": 1, "properties_num_contacted_notes": null, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": null, "properties_numberofemployees": 200, "properties_phone": "+1 415-307-4864", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": null, "properties_recent_deal_close_date": null, "properties_state": "CA", "properties_timezone": "America/Los_Angeles", "properties_total_money_raised": null, "properties_total_revenue": null, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "AirbyteHQ", "properties_type": null, "properties_web_technologies": "slack;segment;google_tag_manager;greenhouse;google_analytics;intercom;piwik;google_apps;hubspot;facebook_advertiser", "properties_website": "airbyte.io", "properties_zip": "94114"}, "emitted_at": 1708012762427} -{"stream": "companies", "data": {"id": "5000526215", "properties": {"about_us": null, "address": null, "address2": null, "annualrevenue": 10000000, "city": "San Francisco", "closedate": "2023-04-04T15:00:58.081000+00:00", "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-11T01:27:40.002000+00:00", "custom_company_property": null, "days_to_close": 844, "description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "domain": "dataline.io", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": "2020-12-11T01:29:50.116000+00:00", "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": "2021-01-13T10:30:42.221000+00:00", "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": "2020-12-11T01:29:50.116000+00:00", "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": "OFFLINE", "hs_analytics_latest_source_data_1": "CONTACTS", "hs_analytics_latest_source_data_2": "CRM_UI", "hs_analytics_latest_source_timestamp": "2020-12-11T01:29:50.153000+00:00", "hs_analytics_num_page_views": 0, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": 0, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": "OFFLINE", "hs_analytics_source_data_1": "CONTACTS", "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": "CRM_UI", "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": "2023-04-04T15:00:58.081000+00:00", "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": "2021-02-23T20:21:06.027000+00:00", "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": "2023-04-04T15:00:58.081000+00:00", "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": "2024-02-06T10:15:00+00:00", "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2024-02-06T10:15:05.376000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": "2024-02-06T10:15:00+00:00", "hs_lead_status": null, "hs_merged_object_ids": "5183403213", "hs_num_blockers": 0, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": 0, "hs_num_decision_makers": 0, "hs_num_open_deals": 2, "hs_object_id": 5000526215, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": "companies-lifecycle-pipeline", "hs_predictivecontactscore_v2": 0.3, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.4857041537761688, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": 27392304072, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": 66508792054, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": 60010, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-11T01:27:40.002000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": "COMPUTER_SOFTWARE", "is_public": false, "lifecyclestage": "customer", "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "name": "Dataline", "notes_last_contacted": "2024-02-06T10:15:00+00:00", "notes_last_updated": "2024-02-06T10:15:00+00:00", "notes_next_activity_date": null, "num_associated_contacts": 1, "num_associated_deals": 3, "num_contacted_notes": 2, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": 2, "numberofemployees": 50, "phone": "", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": 60000, "recent_deal_close_date": "2023-04-04T14:59:45.103000+00:00", "state": "CA", "timezone": "", "total_money_raised": null, "total_revenue": 60000, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "AirbyteHQ", "type": null, "web_technologies": "slack;segment;google_tag_manager;cloud_flare;google_analytics;intercom;lever;google_apps", "website": "dataline.io", "zip": ""}, "createdAt": "2020-12-11T01:27:40.002Z", "updatedAt": "2024-02-06T10:15:05.376Z", "archived": false, "contacts": ["151", "151"], "properties_about_us": null, "properties_address": null, "properties_address2": null, "properties_annualrevenue": 10000000, "properties_city": "San Francisco", "properties_closedate": "2023-04-04T15:00:58.081000+00:00", "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-11T01:27:40.002000+00:00", "properties_custom_company_property": null, "properties_days_to_close": 844, "properties_description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_domain": "dataline.io", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": "2020-12-11T01:29:50.116000+00:00", "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": "2021-01-13T10:30:42.221000+00:00", "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": "2020-12-11T01:29:50.116000+00:00", "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": "OFFLINE", "properties_hs_analytics_latest_source_data_1": "CONTACTS", "properties_hs_analytics_latest_source_data_2": "CRM_UI", "properties_hs_analytics_latest_source_timestamp": "2020-12-11T01:29:50.153000+00:00", "properties_hs_analytics_num_page_views": 0, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": 0, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": "OFFLINE", "properties_hs_analytics_source_data_1": "CONTACTS", "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": "CRM_UI", "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": "2023-04-04T15:00:58.081000+00:00", "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": "2021-02-23T20:21:06.027000+00:00", "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": "2023-04-04T15:00:58.081000+00:00", "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": "2024-02-06T10:15:00+00:00", "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2024-02-06T10:15:05.376000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": "2024-02-06T10:15:00+00:00", "properties_hs_lead_status": null, "properties_hs_merged_object_ids": "5183403213", "properties_hs_num_blockers": 0, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": 0, "properties_hs_num_decision_makers": 0, "properties_hs_num_open_deals": 2, "properties_hs_object_id": 5000526215, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": "companies-lifecycle-pipeline", "properties_hs_predictivecontactscore_v2": 0.3, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.4857041537761688, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": 27392304072, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": 66508792054, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": 60010, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-11T01:27:40.002000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": "COMPUTER_SOFTWARE", "properties_is_public": false, "properties_lifecyclestage": "customer", "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_name": "Dataline", "properties_notes_last_contacted": "2024-02-06T10:15:00+00:00", "properties_notes_last_updated": "2024-02-06T10:15:00+00:00", "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 1, "properties_num_associated_deals": 3, "properties_num_contacted_notes": 2, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": 2, "properties_numberofemployees": 50, "properties_phone": "", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": 60000, "properties_recent_deal_close_date": "2023-04-04T14:59:45.103000+00:00", "properties_state": "CA", "properties_timezone": "", "properties_total_money_raised": null, "properties_total_revenue": 60000, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "AirbyteHQ", "properties_type": null, "properties_web_technologies": "slack;segment;google_tag_manager;cloud_flare;google_analytics;intercom;lever;google_apps", "properties_website": "dataline.io", "properties_zip": ""}, "emitted_at": 1708012762428} -{"stream": "companies", "data": {"id": "5000787595", "properties": {"about_us": null, "address": "2261 Market Street", "address2": null, "annualrevenue": 10000000, "city": "San Francisco", "closedate": null, "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-11T01:28:27.673000+00:00", "custom_company_property": null, "days_to_close": null, "description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "domain": "Daxtarity.com", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": null, "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": null, "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": null, "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": "", "hs_analytics_latest_source_data_1": "", "hs_analytics_latest_source_data_2": "", "hs_analytics_latest_source_timestamp": null, "hs_analytics_num_page_views": null, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": null, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": "", "hs_analytics_source_data_1": "", "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": "", "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": null, "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": null, "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": null, "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": null, "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2024-01-31T23:50:34.138000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": null, "hs_lead_status": null, "hs_merged_object_ids": null, "hs_num_blockers": 0, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": 0, "hs_num_decision_makers": 0, "hs_num_open_deals": 0, "hs_object_id": 5000787595, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": null, "hs_predictivecontactscore_v2": null, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.4076234698295593, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": null, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": null, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": null, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-11T01:28:27.673000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": null, "is_public": false, "lifecyclestage": null, "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "name": "Daxtarity", "notes_last_contacted": null, "notes_last_updated": null, "notes_next_activity_date": null, "num_associated_contacts": 0, "num_associated_deals": null, "num_contacted_notes": null, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": null, "numberofemployees": 50, "phone": "+1 415-307-4864", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": null, "recent_deal_close_date": null, "state": "CA", "timezone": "", "total_money_raised": "31200000", "total_revenue": null, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "AirbyteHQ", "type": null, "web_technologies": "slack;google_tag_manager;greenhouse;google_analytics;intercom;piwik;google_apps;hubspot;facebook_advertiser", "website": "Daxtarity.com", "zip": "94114"}, "createdAt": "2020-12-11T01:28:27.673Z", "updatedAt": "2024-01-31T23:50:34.138Z", "archived": false, "properties_about_us": null, "properties_address": "2261 Market Street", "properties_address2": null, "properties_annualrevenue": 10000000, "properties_city": "San Francisco", "properties_closedate": null, "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-11T01:28:27.673000+00:00", "properties_custom_company_property": null, "properties_days_to_close": null, "properties_description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_domain": "Daxtarity.com", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": null, "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": null, "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": null, "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": "", "properties_hs_analytics_latest_source_data_1": "", "properties_hs_analytics_latest_source_data_2": "", "properties_hs_analytics_latest_source_timestamp": null, "properties_hs_analytics_num_page_views": null, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": null, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": "", "properties_hs_analytics_source_data_1": "", "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": "", "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": null, "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": null, "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": null, "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": null, "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2024-01-31T23:50:34.138000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": null, "properties_hs_lead_status": null, "properties_hs_merged_object_ids": null, "properties_hs_num_blockers": 0, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": 0, "properties_hs_num_decision_makers": 0, "properties_hs_num_open_deals": 0, "properties_hs_object_id": 5000787595, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": null, "properties_hs_predictivecontactscore_v2": null, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.4076234698295593, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": null, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": null, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": null, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-11T01:28:27.673000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": null, "properties_is_public": false, "properties_lifecyclestage": null, "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_name": "Daxtarity", "properties_notes_last_contacted": null, "properties_notes_last_updated": null, "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 0, "properties_num_associated_deals": null, "properties_num_contacted_notes": null, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": null, "properties_numberofemployees": 50, "properties_phone": "+1 415-307-4864", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": null, "properties_recent_deal_close_date": null, "properties_state": "CA", "properties_timezone": "", "properties_total_money_raised": "31200000", "properties_total_revenue": null, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "AirbyteHQ", "properties_type": null, "properties_web_technologies": "slack;google_tag_manager;greenhouse;google_analytics;intercom;piwik;google_apps;hubspot;facebook_advertiser", "properties_website": "Daxtarity.com", "properties_zip": "94114"}, "emitted_at": 1708012762430} +{"stream": "campaigns", "data": {"id": 243851494, "lastUpdatedTime": 1675121674226, "appId": 113, "appName": "Batch", "contentId": 100523515217, "subject": "test", "name": "test", "counters": {"dropped": 1}, "type": "BATCH_EMAIL", "counters_dropped": 1}, "emitted_at": 1708950311366} +{"stream": "campaigns", "data": {"id": 115429485, "lastUpdatedTime": 1615506409286, "appId": 113, "appName": "Batch", "contentId": 42931043849, "subject": "Test subj", "name": "Test subj", "counters": {"processed": 1, "deferred": 1, "mta_dropped": 1, "dropped": 3, "sent": 0}, "type": "BATCH_EMAIL", "counters_processed": 1, "counters_deferred": 1, "counters_mta_dropped": 1, "counters_dropped": 3, "counters_sent": 0}, "emitted_at": 1708950311566} +{"stream": "companies", "data": {"id": "4992593519", "properties": {"about_us": null, "address": null, "address2": null, "annualrevenue": null, "city": "San Francisco", "closedate": null, "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-10T07:58:09.554000+00:00", "custom_company_property": null, "days_to_close": null, "description": "Airbyte.io is an open-source data integration platform that supports both batch and real-time data synchronization. They offer various connectors to integrate data from different sources like databases, APIs, file storage systems, and more. Airbyte.io ...", "domain": "airbyte.io", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": null, "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": "2021-05-21T10:17:06.028000+00:00", "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": null, "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": null, "hs_analytics_latest_source_data_1": null, "hs_analytics_latest_source_data_2": null, "hs_analytics_latest_source_timestamp": null, "hs_analytics_num_page_views": null, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": null, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": null, "hs_analytics_source_data_1": null, "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": null, "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": null, "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": "2021-05-21T10:17:28.964000+00:00", "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": null, "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": null, "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2024-02-17T01:21:12.230000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": null, "hs_lead_status": null, "hs_merged_object_ids": null, "hs_num_blockers": null, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": null, "hs_num_decision_makers": null, "hs_num_open_deals": 1, "hs_object_id": 4992593519, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": null, "hs_predictivecontactscore_v2": null, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.5476861596107483, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": null, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": 87359064741, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": null, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-10T07:58:09.554000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": null, "is_public": false, "lifecyclestage": "opportunity", "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "Airbyte.io is an open-source data integration platform that supports both batch and real-time data synchronization. They offer various connectors to integrate data from different sources like databases, APIs, file storage systems, and more. Airbyte.io ...", "name": "Airbyte test1", "notes_last_contacted": null, "notes_last_updated": null, "notes_next_activity_date": null, "num_associated_contacts": 0, "num_associated_deals": 1, "num_contacted_notes": null, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": null, "numberofemployees": 200, "phone": "+1 415-307-4864", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": null, "recent_deal_close_date": null, "state": "CA", "timezone": "America/Los_Angeles", "total_money_raised": null, "total_revenue": null, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "AirbyteHQ", "type": null, "web_technologies": "slack;google_tag_manager;google_analytics;intercom;lever;google_apps", "website": "airbyte.io", "zip": "94114"}, "createdAt": "2020-12-10T07:58:09.554Z", "updatedAt": "2024-02-17T01:21:12.230Z", "archived": false, "properties_about_us": null, "properties_address": null, "properties_address2": null, "properties_annualrevenue": null, "properties_city": "San Francisco", "properties_closedate": null, "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-10T07:58:09.554000+00:00", "properties_custom_company_property": null, "properties_days_to_close": null, "properties_description": "Airbyte.io is an open-source data integration platform that supports both batch and real-time data synchronization. They offer various connectors to integrate data from different sources like databases, APIs, file storage systems, and more. Airbyte.io ...", "properties_domain": "airbyte.io", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": null, "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": "2021-05-21T10:17:06.028000+00:00", "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": null, "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": null, "properties_hs_analytics_latest_source_data_1": null, "properties_hs_analytics_latest_source_data_2": null, "properties_hs_analytics_latest_source_timestamp": null, "properties_hs_analytics_num_page_views": null, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": null, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": null, "properties_hs_analytics_source_data_1": null, "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": null, "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": null, "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": "2021-05-21T10:17:28.964000+00:00", "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": null, "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": null, "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2024-02-17T01:21:12.230000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": null, "properties_hs_lead_status": null, "properties_hs_merged_object_ids": null, "properties_hs_num_blockers": null, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": null, "properties_hs_num_decision_makers": null, "properties_hs_num_open_deals": 1, "properties_hs_object_id": 4992593519, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": null, "properties_hs_predictivecontactscore_v2": null, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.5476861596107483, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": null, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": 87359064741, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": null, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-10T07:58:09.554000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": null, "properties_is_public": false, "properties_lifecyclestage": "opportunity", "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "Airbyte.io is an open-source data integration platform that supports both batch and real-time data synchronization. They offer various connectors to integrate data from different sources like databases, APIs, file storage systems, and more. Airbyte.io ...", "properties_name": "Airbyte test1", "properties_notes_last_contacted": null, "properties_notes_last_updated": null, "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 0, "properties_num_associated_deals": 1, "properties_num_contacted_notes": null, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": null, "properties_numberofemployees": 200, "properties_phone": "+1 415-307-4864", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": null, "properties_recent_deal_close_date": null, "properties_state": "CA", "properties_timezone": "America/Los_Angeles", "properties_total_money_raised": null, "properties_total_revenue": null, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "AirbyteHQ", "properties_type": null, "properties_web_technologies": "slack;google_tag_manager;google_analytics;intercom;lever;google_apps", "properties_website": "airbyte.io", "properties_zip": "94114"}, "emitted_at": 1708951313817} +{"stream": "companies", "data": {"id": "5000526215", "properties": {"about_us": null, "address": null, "address2": null, "annualrevenue": 10000000, "city": "San Francisco", "closedate": "2023-04-04T15:00:58.081000+00:00", "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-11T01:27:40.002000+00:00", "custom_company_property": null, "days_to_close": 844, "description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "domain": "dataline.io", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": "2020-12-11T01:29:50.116000+00:00", "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": "2021-01-13T10:30:42.221000+00:00", "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": "2020-12-11T01:29:50.116000+00:00", "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": "OFFLINE", "hs_analytics_latest_source_data_1": "CONTACTS", "hs_analytics_latest_source_data_2": "CRM_UI", "hs_analytics_latest_source_timestamp": "2020-12-11T01:29:50.153000+00:00", "hs_analytics_num_page_views": 0, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": 0, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": "OFFLINE", "hs_analytics_source_data_1": "CONTACTS", "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": "CRM_UI", "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": "2023-04-04T15:00:58.081000+00:00", "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": "2021-02-23T20:21:06.027000+00:00", "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": "2023-04-04T15:00:58.081000+00:00", "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": "2024-02-06T10:15:00+00:00", "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2024-02-22T19:26:33.386000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": "2024-02-06T10:15:00+00:00", "hs_lead_status": null, "hs_merged_object_ids": "5183403213", "hs_num_blockers": 0, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": 0, "hs_num_decision_makers": 0, "hs_num_open_deals": 2, "hs_object_id": 5000526215, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": "companies-lifecycle-pipeline", "hs_predictivecontactscore_v2": 0.3, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.4857041537761688, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": 28330855624, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": 66508792054, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": 60010, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-11T01:27:40.002000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": "COMPUTER_SOFTWARE", "is_public": false, "lifecyclestage": "customer", "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "name": "Dataline", "notes_last_contacted": "2024-02-06T10:15:00+00:00", "notes_last_updated": "2024-02-06T10:15:00+00:00", "notes_next_activity_date": null, "num_associated_contacts": 1, "num_associated_deals": 3, "num_contacted_notes": 2, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": 2, "numberofemployees": 10, "phone": "", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": 60000, "recent_deal_close_date": "2023-04-04T14:59:45.103000+00:00", "state": "CA", "timezone": "America/Los_Angeles", "total_money_raised": null, "total_revenue": 60000, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "AirbyteHQ", "type": null, "web_technologies": "wordpress;segment;google_tag_manager;cloud_flare;google_apps;hubspot;drift", "website": "dataline.io", "zip": ""}, "createdAt": "2020-12-11T01:27:40.002Z", "updatedAt": "2024-02-22T19:26:33.386Z", "archived": false, "contacts": ["151", "151"], "properties_about_us": null, "properties_address": null, "properties_address2": null, "properties_annualrevenue": 10000000, "properties_city": "San Francisco", "properties_closedate": "2023-04-04T15:00:58.081000+00:00", "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-11T01:27:40.002000+00:00", "properties_custom_company_property": null, "properties_days_to_close": 844, "properties_description": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_domain": "dataline.io", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": "2020-12-11T01:29:50.116000+00:00", "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": "2021-01-13T10:30:42.221000+00:00", "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": "2020-12-11T01:29:50.116000+00:00", "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": "OFFLINE", "properties_hs_analytics_latest_source_data_1": "CONTACTS", "properties_hs_analytics_latest_source_data_2": "CRM_UI", "properties_hs_analytics_latest_source_timestamp": "2020-12-11T01:29:50.153000+00:00", "properties_hs_analytics_num_page_views": 0, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": 0, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": "OFFLINE", "properties_hs_analytics_source_data_1": "CONTACTS", "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": "CRM_UI", "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": "2023-04-04T15:00:58.081000+00:00", "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": "2021-02-23T20:21:06.027000+00:00", "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": "2023-04-04T15:00:58.081000+00:00", "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": "2024-02-06T10:15:00+00:00", "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2024-02-22T19:26:33.386000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": "2024-02-06T10:15:00+00:00", "properties_hs_lead_status": null, "properties_hs_merged_object_ids": "5183403213", "properties_hs_num_blockers": 0, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": 0, "properties_hs_num_decision_makers": 0, "properties_hs_num_open_deals": 2, "properties_hs_object_id": 5000526215, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": "companies-lifecycle-pipeline", "properties_hs_predictivecontactscore_v2": 0.3, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.4857041537761688, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": 28330855624, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": 66508792054, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": 60010, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-11T01:27:40.002000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": "COMPUTER_SOFTWARE", "properties_is_public": false, "properties_lifecyclestage": "customer", "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "Airbyte is an open-source data integration platform to build ELT pipelines. Consolidate your data in your data warehouses, lakes and databases.", "properties_name": "Dataline", "properties_notes_last_contacted": "2024-02-06T10:15:00+00:00", "properties_notes_last_updated": "2024-02-06T10:15:00+00:00", "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 1, "properties_num_associated_deals": 3, "properties_num_contacted_notes": 2, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": 2, "properties_numberofemployees": 10, "properties_phone": "", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": 60000, "properties_recent_deal_close_date": "2023-04-04T14:59:45.103000+00:00", "properties_state": "CA", "properties_timezone": "America/Los_Angeles", "properties_total_money_raised": null, "properties_total_revenue": 60000, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "AirbyteHQ", "properties_type": null, "properties_web_technologies": "wordpress;segment;google_tag_manager;cloud_flare;google_apps;hubspot;drift", "properties_website": "dataline.io", "properties_zip": ""}, "emitted_at": 1708951313819} +{"stream": "companies", "data": {"id": "5000787595", "properties": {"about_us": null, "address": "2261 Market Street", "address2": null, "annualrevenue": 10000000, "city": "San Francisco", "closedate": null, "closedate_timestamp_earliest_value_a2a17e6e": null, "country": "United States", "createdate": "2020-12-11T01:28:27.673000+00:00", "custom_company_property": null, "days_to_close": null, "description": "On a mission to remove all the friction and operational costs when ingesting 3rd-party data, at scale.", "domain": "Daxtarity.com", "engagements_last_meeting_booked": null, "engagements_last_meeting_booked_campaign": null, "engagements_last_meeting_booked_medium": null, "engagements_last_meeting_booked_source": null, "facebook_company_page": null, "facebookfans": null, "first_contact_createdate": null, "first_contact_createdate_timestamp_earliest_value_78b50eea": null, "first_conversion_date": null, "first_conversion_date_timestamp_earliest_value_61f58f2c": null, "first_conversion_event_name": null, "first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "first_deal_created_date": null, "founded_year": "2020", "googleplus_page": null, "hs_additional_domains": null, "hs_all_accessible_team_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_analytics_first_timestamp": null, "hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "hs_analytics_first_touch_converting_campaign": null, "hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "hs_analytics_first_visit_timestamp": null, "hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "hs_analytics_last_timestamp": null, "hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "hs_analytics_last_touch_converting_campaign": null, "hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "hs_analytics_last_visit_timestamp": null, "hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "hs_analytics_latest_source": "", "hs_analytics_latest_source_data_1": "", "hs_analytics_latest_source_data_2": "", "hs_analytics_latest_source_timestamp": null, "hs_analytics_num_page_views": null, "hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "hs_analytics_num_visits": null, "hs_analytics_num_visits_cardinality_sum_53d952a6": null, "hs_analytics_source": "", "hs_analytics_source_data_1": "", "hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "hs_analytics_source_data_2": "", "hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "hs_annual_revenue_currency_code": "USD", "hs_avatar_filemanager_key": null, "hs_created_by_user_id": 12282590, "hs_createdate": null, "hs_date_entered_customer": null, "hs_date_entered_evangelist": null, "hs_date_entered_lead": null, "hs_date_entered_marketingqualifiedlead": null, "hs_date_entered_opportunity": null, "hs_date_entered_other": null, "hs_date_entered_salesqualifiedlead": null, "hs_date_entered_subscriber": null, "hs_date_exited_customer": null, "hs_date_exited_evangelist": null, "hs_date_exited_lead": null, "hs_date_exited_marketingqualifiedlead": null, "hs_date_exited_opportunity": null, "hs_date_exited_other": null, "hs_date_exited_salesqualifiedlead": null, "hs_date_exited_subscriber": null, "hs_ideal_customer_profile": null, "hs_is_target_account": null, "hs_last_booked_meeting_date": null, "hs_last_logged_call_date": null, "hs_last_open_task_date": null, "hs_last_sales_activity_date": null, "hs_last_sales_activity_timestamp": null, "hs_last_sales_activity_type": null, "hs_lastmodifieddate": "2024-02-22T18:31:08.404000+00:00", "hs_latest_createdate_of_active_subscriptions": null, "hs_latest_meeting_activity": null, "hs_lead_status": null, "hs_merged_object_ids": null, "hs_num_blockers": 0, "hs_num_child_companies": 0, "hs_num_contacts_with_buying_roles": 0, "hs_num_decision_makers": 0, "hs_num_open_deals": 0, "hs_object_id": 5000787595, "hs_object_source": "CONTACTS", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "CRM_UI", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_parent_company_id": null, "hs_pinned_engagement_id": null, "hs_pipeline": null, "hs_predictivecontactscore_v2": null, "hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "hs_read_only": null, "hs_sales_email_last_replied": null, "hs_target_account": null, "hs_target_account_probability": 0.4076234698295593, "hs_target_account_recommendation_snooze_time": null, "hs_target_account_recommendation_state": null, "hs_time_in_customer": null, "hs_time_in_evangelist": null, "hs_time_in_lead": null, "hs_time_in_marketingqualifiedlead": null, "hs_time_in_opportunity": null, "hs_time_in_other": null, "hs_time_in_salesqualifiedlead": null, "hs_time_in_subscriber": null, "hs_total_deal_value": null, "hs_unique_creation_key": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2020-12-11T01:28:27.673000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null, "hubspotscore": null, "industry": "COMPUTER_SOFTWARE", "is_public": false, "lifecyclestage": null, "linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "linkedinbio": "On a mission to remove all the friction and operational costs when ingesting 3rd-party data, at scale.", "name": "Daxtarity", "notes_last_contacted": null, "notes_last_updated": null, "notes_next_activity_date": null, "num_associated_contacts": 0, "num_associated_deals": null, "num_contacted_notes": null, "num_conversion_events": null, "num_conversion_events_cardinality_sum_d095f14b": null, "num_notes": null, "numberofemployees": 50, "phone": "+1 415-307-4864", "recent_conversion_date": null, "recent_conversion_date_timestamp_latest_value_72856da1": null, "recent_conversion_event_name": null, "recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "recent_deal_amount": null, "recent_deal_close_date": null, "state": "CA", "timezone": "America/Los_Angeles", "total_money_raised": "31200000", "total_revenue": null, "twitterbio": null, "twitterfollowers": null, "twitterhandle": "DaxtarityHq", "type": null, "web_technologies": "nginx;wordpress;bluehost_hosting;google_apps", "website": "Daxtarity.com", "zip": "94114"}, "createdAt": "2020-12-11T01:28:27.673Z", "updatedAt": "2024-02-22T18:31:08.404Z", "archived": false, "properties_about_us": null, "properties_address": "2261 Market Street", "properties_address2": null, "properties_annualrevenue": 10000000, "properties_city": "San Francisco", "properties_closedate": null, "properties_closedate_timestamp_earliest_value_a2a17e6e": null, "properties_country": "United States", "properties_createdate": "2020-12-11T01:28:27.673000+00:00", "properties_custom_company_property": null, "properties_days_to_close": null, "properties_description": "On a mission to remove all the friction and operational costs when ingesting 3rd-party data, at scale.", "properties_domain": "Daxtarity.com", "properties_engagements_last_meeting_booked": null, "properties_engagements_last_meeting_booked_campaign": null, "properties_engagements_last_meeting_booked_medium": null, "properties_engagements_last_meeting_booked_source": null, "properties_facebook_company_page": null, "properties_facebookfans": null, "properties_first_contact_createdate": null, "properties_first_contact_createdate_timestamp_earliest_value_78b50eea": null, "properties_first_conversion_date": null, "properties_first_conversion_date_timestamp_earliest_value_61f58f2c": null, "properties_first_conversion_event_name": null, "properties_first_conversion_event_name_timestamp_earliest_value_68ddae0a": null, "properties_first_deal_created_date": null, "properties_founded_year": "2020", "properties_googleplus_page": null, "properties_hs_additional_domains": null, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_analytics_first_timestamp": null, "properties_hs_analytics_first_timestamp_timestamp_earliest_value_11e3a63a": null, "properties_hs_analytics_first_touch_converting_campaign": null, "properties_hs_analytics_first_touch_converting_campaign_timestamp_earliest_value_4757fe10": null, "properties_hs_analytics_first_visit_timestamp": null, "properties_hs_analytics_first_visit_timestamp_timestamp_earliest_value_accc17ae": null, "properties_hs_analytics_last_timestamp": null, "properties_hs_analytics_last_timestamp_timestamp_latest_value_4e16365a": null, "properties_hs_analytics_last_touch_converting_campaign": null, "properties_hs_analytics_last_touch_converting_campaign_timestamp_latest_value_81a64e30": null, "properties_hs_analytics_last_visit_timestamp": null, "properties_hs_analytics_last_visit_timestamp_timestamp_latest_value_999a0fce": null, "properties_hs_analytics_latest_source": "", "properties_hs_analytics_latest_source_data_1": "", "properties_hs_analytics_latest_source_data_2": "", "properties_hs_analytics_latest_source_timestamp": null, "properties_hs_analytics_num_page_views": null, "properties_hs_analytics_num_page_views_cardinality_sum_e46e85b0": null, "properties_hs_analytics_num_visits": null, "properties_hs_analytics_num_visits_cardinality_sum_53d952a6": null, "properties_hs_analytics_source": "", "properties_hs_analytics_source_data_1": "", "properties_hs_analytics_source_data_1_timestamp_earliest_value_9b2f1fa1": null, "properties_hs_analytics_source_data_2": "", "properties_hs_analytics_source_data_2_timestamp_earliest_value_9b2f9400": null, "properties_hs_analytics_source_timestamp_earliest_value_25a3a52c": null, "properties_hs_annual_revenue_currency_code": "USD", "properties_hs_avatar_filemanager_key": null, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": null, "properties_hs_date_entered_customer": null, "properties_hs_date_entered_evangelist": null, "properties_hs_date_entered_lead": null, "properties_hs_date_entered_marketingqualifiedlead": null, "properties_hs_date_entered_opportunity": null, "properties_hs_date_entered_other": null, "properties_hs_date_entered_salesqualifiedlead": null, "properties_hs_date_entered_subscriber": null, "properties_hs_date_exited_customer": null, "properties_hs_date_exited_evangelist": null, "properties_hs_date_exited_lead": null, "properties_hs_date_exited_marketingqualifiedlead": null, "properties_hs_date_exited_opportunity": null, "properties_hs_date_exited_other": null, "properties_hs_date_exited_salesqualifiedlead": null, "properties_hs_date_exited_subscriber": null, "properties_hs_ideal_customer_profile": null, "properties_hs_is_target_account": null, "properties_hs_last_booked_meeting_date": null, "properties_hs_last_logged_call_date": null, "properties_hs_last_open_task_date": null, "properties_hs_last_sales_activity_date": null, "properties_hs_last_sales_activity_timestamp": null, "properties_hs_last_sales_activity_type": null, "properties_hs_lastmodifieddate": "2024-02-22T18:31:08.404000+00:00", "properties_hs_latest_createdate_of_active_subscriptions": null, "properties_hs_latest_meeting_activity": null, "properties_hs_lead_status": null, "properties_hs_merged_object_ids": null, "properties_hs_num_blockers": 0, "properties_hs_num_child_companies": 0, "properties_hs_num_contacts_with_buying_roles": 0, "properties_hs_num_decision_makers": 0, "properties_hs_num_open_deals": 0, "properties_hs_object_id": 5000787595, "properties_hs_object_source": "CONTACTS", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "CRM_UI", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_parent_company_id": null, "properties_hs_pinned_engagement_id": null, "properties_hs_pipeline": null, "properties_hs_predictivecontactscore_v2": null, "properties_hs_predictivecontactscore_v2_next_max_max_d4e58c1e": null, "properties_hs_read_only": null, "properties_hs_sales_email_last_replied": null, "properties_hs_target_account": null, "properties_hs_target_account_probability": 0.4076234698295593, "properties_hs_target_account_recommendation_snooze_time": null, "properties_hs_target_account_recommendation_state": null, "properties_hs_time_in_customer": null, "properties_hs_time_in_evangelist": null, "properties_hs_time_in_lead": null, "properties_hs_time_in_marketingqualifiedlead": null, "properties_hs_time_in_opportunity": null, "properties_hs_time_in_other": null, "properties_hs_time_in_salesqualifiedlead": null, "properties_hs_time_in_subscriber": null, "properties_hs_total_deal_value": null, "properties_hs_unique_creation_key": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2020-12-11T01:28:27.673000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null, "properties_hubspotscore": null, "properties_industry": "COMPUTER_SOFTWARE", "properties_is_public": false, "properties_lifecyclestage": null, "properties_linkedin_company_page": "https://www.linkedin.com/company/airbytehq", "properties_linkedinbio": "On a mission to remove all the friction and operational costs when ingesting 3rd-party data, at scale.", "properties_name": "Daxtarity", "properties_notes_last_contacted": null, "properties_notes_last_updated": null, "properties_notes_next_activity_date": null, "properties_num_associated_contacts": 0, "properties_num_associated_deals": null, "properties_num_contacted_notes": null, "properties_num_conversion_events": null, "properties_num_conversion_events_cardinality_sum_d095f14b": null, "properties_num_notes": null, "properties_numberofemployees": 50, "properties_phone": "+1 415-307-4864", "properties_recent_conversion_date": null, "properties_recent_conversion_date_timestamp_latest_value_72856da1": null, "properties_recent_conversion_event_name": null, "properties_recent_conversion_event_name_timestamp_latest_value_66c820bf": null, "properties_recent_deal_amount": null, "properties_recent_deal_close_date": null, "properties_state": "CA", "properties_timezone": "America/Los_Angeles", "properties_total_money_raised": "31200000", "properties_total_revenue": null, "properties_twitterbio": null, "properties_twitterfollowers": null, "properties_twitterhandle": "DaxtarityHq", "properties_type": null, "properties_web_technologies": "nginx;wordpress;bluehost_hosting;google_apps", "properties_website": "Daxtarity.com", "properties_zip": "94114"}, "emitted_at": 1708951313821} {"stream": "contact_lists", "data": {"portalId": 8727216, "listId": 1, "createdAt": 1610634707370, "updatedAt": 1610634721116, "name": "tweeters", "listType": "DYNAMIC", "authorId": 0, "filters": [], "metaData": {"size": 0, "lastSizeChangeAt": 1625270400000, "processing": "DONE", "lastProcessingStateChangeAt": 1610634721950, "error": "", "listReferencesCount": null, "parentFolderId": null}, "archived": false, "teamIds": [], "ilsFilterBranch": "{\"filterBranchOperator\":\"OR\",\"filters\":[],\"filterBranches\":[{\"filterBranchOperator\":\"AND\",\"filters\":[{\"filterType\":\"PROPERTY\",\"property\":\"twitterhandle\",\"operation\":{\"propertyType\":\"string\",\"operator\":\"IS_EQUAL_TO\",\"value\":\"@hubspot\",\"defaultValue\":null,\"includeObjectsWithNoValueSet\":false,\"operationType\":\"string\",\"operatorName\":\"IS_EQUAL_TO\"},\"frameworkFilterId\":null}],\"filterBranches\":[],\"filterBranchType\":\"AND\"}],\"filterBranchType\":\"OR\"}", "readOnly": false, "dynamic": true, "internal": false, "limitExempt": false, "metaData_size": 0, "metaData_lastSizeChangeAt": 1625270400000, "metaData_processing": "DONE", "metaData_lastProcessingStateChangeAt": 1610634721950, "metaData_error": "", "metaData_listReferencesCount": null, "metaData_parentFolderId": null}, "emitted_at": 1697714189110} {"stream": "contact_lists", "data": {"portalId": 8727216, "listId": 2, "createdAt": 1610634770432, "updatedAt": 1610634780637, "name": "tweeters 1", "listType": "DYNAMIC", "authorId": 0, "filters": [], "metaData": {"size": 0, "lastSizeChangeAt": 1625270400000, "processing": "DONE", "lastProcessingStateChangeAt": 1610634781147, "error": "", "listReferencesCount": null, "parentFolderId": null}, "archived": false, "teamIds": [], "ilsFilterBranch": "{\"filterBranchOperator\":\"OR\",\"filters\":[],\"filterBranches\":[{\"filterBranchOperator\":\"AND\",\"filters\":[{\"filterType\":\"PROPERTY\",\"property\":\"twitterhandle\",\"operation\":{\"propertyType\":\"string\",\"operator\":\"IS_EQUAL_TO\",\"value\":\"@hubspot\",\"defaultValue\":null,\"includeObjectsWithNoValueSet\":false,\"operationType\":\"string\",\"operatorName\":\"IS_EQUAL_TO\"},\"frameworkFilterId\":null}],\"filterBranches\":[],\"filterBranchType\":\"AND\"}],\"filterBranchType\":\"OR\"}", "readOnly": false, "dynamic": true, "internal": false, "limitExempt": false, "metaData_size": 0, "metaData_lastSizeChangeAt": 1625270400000, "metaData_processing": "DONE", "metaData_lastProcessingStateChangeAt": 1610634781147, "metaData_error": "", "metaData_listReferencesCount": null, "metaData_parentFolderId": null}, "emitted_at": 1697714189112} {"stream": "contact_lists", "data": {"portalId": 8727216, "listId": 3, "createdAt": 1610634774356, "updatedAt": 1610634787734, "name": "tweeters 2", "listType": "DYNAMIC", "authorId": 0, "filters": [], "metaData": {"size": 0, "lastSizeChangeAt": 1625270400000, "processing": "DONE", "lastProcessingStateChangeAt": 1610634788528, "error": "", "listReferencesCount": null, "parentFolderId": null}, "archived": false, "teamIds": [], "ilsFilterBranch": "{\"filterBranchOperator\":\"OR\",\"filters\":[],\"filterBranches\":[{\"filterBranchOperator\":\"AND\",\"filters\":[{\"filterType\":\"PROPERTY\",\"property\":\"twitterhandle\",\"operation\":{\"propertyType\":\"string\",\"operator\":\"IS_EQUAL_TO\",\"value\":\"@hubspot\",\"defaultValue\":null,\"includeObjectsWithNoValueSet\":false,\"operationType\":\"string\",\"operatorName\":\"IS_EQUAL_TO\"},\"frameworkFilterId\":null}],\"filterBranches\":[],\"filterBranchType\":\"AND\"}],\"filterBranchType\":\"OR\"}", "readOnly": false, "dynamic": true, "internal": false, "limitExempt": false, "metaData_size": 0, "metaData_lastSizeChangeAt": 1625270400000, "metaData_processing": "DONE", "metaData_lastProcessingStateChangeAt": 1610634788528, "metaData_error": "", "metaData_listReferencesCount": null, "metaData_parentFolderId": null}, "emitted_at": 1697714189113} @@ -29,9 +29,9 @@ {"stream": "engagements_notes", "data": {"id": "10584327028", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": "4241968539", "hs_body_preview": "note body 5", "hs_body_preview_html": "\n \n \n note body 5\n \n", "hs_body_preview_is_truncated": false, "hs_created_by": null, "hs_created_by_user_id": null, "hs_createdate": "2021-01-14T14:59:32.009000+00:00", "hs_engagement_source": null, "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": false, "hs_lastmodifieddate": "2021-01-14T14:59:32.009000+00:00", "hs_merged_object_ids": null, "hs_modified_by": null, "hs_note_body": "note body 5", "hs_note_ms_teams_payload": null, "hs_object_id": 10584327028, "hs_object_source": "API", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": null, "hs_object_source_label": "INTERNAL_PROCESSING", "hs_object_source_user_id": null, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": null, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": null, "hs_was_imported": null, "hubspot_owner_assigneddate": null, "hubspot_owner_id": "", "hubspot_team_id": null}, "createdAt": "2021-01-14T14:59:32.009Z", "updatedAt": "2021-01-14T14:59:32.009Z", "archived": false, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": "4241968539", "properties_hs_body_preview": "note body 5", "properties_hs_body_preview_html": "\n \n \n note body 5\n \n", "properties_hs_body_preview_is_truncated": false, "properties_hs_created_by": null, "properties_hs_created_by_user_id": null, "properties_hs_createdate": "2021-01-14T14:59:32.009000+00:00", "properties_hs_engagement_source": null, "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": false, "properties_hs_lastmodifieddate": "2021-01-14T14:59:32.009000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": null, "properties_hs_note_body": "note body 5", "properties_hs_note_ms_teams_payload": null, "properties_hs_object_id": 10584327028, "properties_hs_object_source": "API", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": null, "properties_hs_object_source_label": "INTERNAL_PROCESSING", "properties_hs_object_source_user_id": null, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": null, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": null, "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": null, "properties_hubspot_owner_id": "", "properties_hubspot_team_id": null}, "emitted_at": 1708013474865} {"stream": "engagements_notes", "data": {"id": "10584327043", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": "4241968539", "hs_body_preview": "note body 7", "hs_body_preview_html": "\n \n \n note body 7\n \n", "hs_body_preview_is_truncated": false, "hs_created_by": null, "hs_created_by_user_id": null, "hs_createdate": "2021-01-14T14:59:32.714000+00:00", "hs_engagement_source": null, "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": false, "hs_lastmodifieddate": "2021-01-14T14:59:32.714000+00:00", "hs_merged_object_ids": null, "hs_modified_by": null, "hs_note_body": "note body 7", "hs_note_ms_teams_payload": null, "hs_object_id": 10584327043, "hs_object_source": "API", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": null, "hs_object_source_label": "INTERNAL_PROCESSING", "hs_object_source_user_id": null, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": null, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": null, "hs_was_imported": null, "hubspot_owner_assigneddate": null, "hubspot_owner_id": "", "hubspot_team_id": null}, "createdAt": "2021-01-14T14:59:32.714Z", "updatedAt": "2021-01-14T14:59:32.714Z", "archived": false, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": "4241968539", "properties_hs_body_preview": "note body 7", "properties_hs_body_preview_html": "\n \n \n note body 7\n \n", "properties_hs_body_preview_is_truncated": false, "properties_hs_created_by": null, "properties_hs_created_by_user_id": null, "properties_hs_createdate": "2021-01-14T14:59:32.714000+00:00", "properties_hs_engagement_source": null, "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": false, "properties_hs_lastmodifieddate": "2021-01-14T14:59:32.714000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": null, "properties_hs_note_body": "note body 7", "properties_hs_note_ms_teams_payload": null, "properties_hs_object_id": 10584327043, "properties_hs_object_source": "API", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": null, "properties_hs_object_source_label": "INTERNAL_PROCESSING", "properties_hs_object_source_user_id": null, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": null, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": null, "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": null, "properties_hubspot_owner_id": "", "properties_hubspot_team_id": null}, "emitted_at": 1708013474865} {"stream": "engagements_notes", "data": {"id": "10584344127", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": "4241968539", "hs_body_preview": "note body", "hs_body_preview_html": "\n \n \n note body\n \n", "hs_body_preview_is_truncated": false, "hs_created_by": null, "hs_created_by_user_id": null, "hs_createdate": "2021-01-14T14:58:40.990000+00:00", "hs_engagement_source": null, "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": false, "hs_lastmodifieddate": "2021-01-14T14:58:40.990000+00:00", "hs_merged_object_ids": null, "hs_modified_by": null, "hs_note_body": "note body", "hs_note_ms_teams_payload": null, "hs_object_id": 10584344127, "hs_object_source": "API", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": null, "hs_object_source_label": "INTERNAL_PROCESSING", "hs_object_source_user_id": null, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": null, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": null, "hs_was_imported": null, "hubspot_owner_assigneddate": null, "hubspot_owner_id": "", "hubspot_team_id": null}, "createdAt": "2021-01-14T14:58:40.990Z", "updatedAt": "2021-01-14T14:58:40.990Z", "archived": false, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": "4241968539", "properties_hs_body_preview": "note body", "properties_hs_body_preview_html": "\n \n \n note body\n \n", "properties_hs_body_preview_is_truncated": false, "properties_hs_created_by": null, "properties_hs_created_by_user_id": null, "properties_hs_createdate": "2021-01-14T14:58:40.990000+00:00", "properties_hs_engagement_source": null, "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": false, "properties_hs_lastmodifieddate": "2021-01-14T14:58:40.990000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": null, "properties_hs_note_body": "note body", "properties_hs_note_ms_teams_payload": null, "properties_hs_object_id": 10584344127, "properties_hs_object_source": "API", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": null, "properties_hs_object_source_label": "INTERNAL_PROCESSING", "properties_hs_object_source_user_id": null, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_timestamp": "2014-08-27T20:50:44.778000+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": null, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": null, "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": null, "properties_hubspot_owner_id": "", "properties_hubspot_team_id": null}, "emitted_at": 1708013474865} -{"stream": "engagements_tasks", "data": {"id": "11257289597", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "hs_body_preview_html": "\n \n \n Regarding note logged on Tuesday, February 23, 2021 10:25 PM\n \n", "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2021-02-23T20:25:07.503000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": null, "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": false, "hs_lastmodifieddate": "2023-04-19T14:52:43.485000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 11257289597, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[{\"engagementId\":11257289597,\"portalId\":8727216,\"engagementType\":\"TASK\",\"taskType\":\"REMINDER\",\"timestamp\":1614319200000,\"uuid\":\"TASK:e41fd851-f7c7-4381-85fa-796d076163aa\"}]}", "hs_task_body": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": null, "hs_task_reminders": "1614319200000", "hs_task_repeat_interval": null, "hs_task_send_default_reminder": null, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "Follow up on Test deal 2", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2021-02-26T06:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2021-02-23T20:25:07.503000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2021-02-23T20:25:07.503Z", "updatedAt": "2023-04-19T14:52:43.485Z", "archived": false, "deals": ["4315375411"], "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "properties_hs_body_preview_html": "\n \n \n Regarding note logged on Tuesday, February 23, 2021 10:25 PM\n \n", "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2021-02-23T20:25:07.503000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": null, "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": false, "properties_hs_lastmodifieddate": "2023-04-19T14:52:43.485000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 11257289597, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[{\"engagementId\":11257289597,\"portalId\":8727216,\"engagementType\":\"TASK\",\"taskType\":\"REMINDER\",\"timestamp\":1614319200000,\"uuid\":\"TASK:e41fd851-f7c7-4381-85fa-796d076163aa\"}]}", "properties_hs_task_body": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": null, "properties_hs_task_reminders": "1614319200000", "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": null, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "Follow up on Test deal 2", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2021-02-26T06:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2021-02-23T20:25:07.503000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708013653895} -{"stream": "engagements_tasks", "data": {"id": "30652597343", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": null, "hs_body_preview_html": null, "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2023-01-30T23:41:48.834000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": "CRM_UI", "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": null, "hs_lastmodifieddate": "2023-04-04T15:11:47.231000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 30652597343, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "hs_task_body": null, "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": "[]", "hs_task_reminders": null, "hs_task_repeat_interval": null, "hs_task_send_default_reminder": false, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "test", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2023-02-03T07:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2023-01-30T23:41:48.834000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2023-01-30T23:41:48.834Z", "updatedAt": "2023-04-04T15:11:47.231Z", "archived": false, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": null, "properties_hs_body_preview_html": null, "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2023-01-30T23:41:48.834000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": "CRM_UI", "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": null, "properties_hs_lastmodifieddate": "2023-04-04T15:11:47.231000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 30652597343, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "properties_hs_task_body": null, "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": "[]", "properties_hs_task_reminders": null, "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": false, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "test", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2023-02-03T07:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2023-01-30T23:41:48.834000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708013653896} -{"stream": "engagements_tasks", "data": {"id": "30652613208", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": null, "hs_body_preview_html": null, "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2023-01-30T23:51:52.099000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": "CRM_UI", "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": null, "hs_lastmodifieddate": "2023-01-30T23:51:54.343000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 30652613208, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "hs_task_body": null, "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": "[]", "hs_task_reminders": null, "hs_task_repeat_interval": null, "hs_task_send_default_reminder": false, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "test", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2023-02-03T07:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2023-01-30T23:51:52.099000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2023-01-30T23:51:52.099Z", "updatedAt": "2023-01-30T23:51:54.343Z", "archived": false, "companies": ["11481383026"], "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": null, "properties_hs_body_preview_html": null, "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2023-01-30T23:51:52.099000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": "CRM_UI", "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": null, "properties_hs_lastmodifieddate": "2023-01-30T23:51:54.343000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 30652613208, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "properties_hs_task_body": null, "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": "[]", "properties_hs_task_reminders": null, "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": false, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "test", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2023-02-03T07:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2023-01-30T23:51:52.099000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708013653897} +{"stream": "engagements_tasks", "data": {"id": "11257289597", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "hs_body_preview_html": "\n \n \n Regarding note logged on Tuesday, February 23, 2021 10:25 PM\n \n", "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2021-02-23T20:25:07.503000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-17T18:41:26.373000+00:00", "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": null, "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": false, "hs_lastmodifieddate": "2023-04-19T14:52:43.485000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 11257289597, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[{\"engagementId\":11257289597,\"portalId\":8727216,\"engagementType\":\"TASK\",\"taskType\":\"REMINDER\",\"timestamp\":1614319200000,\"uuid\":\"TASK:e41fd851-f7c7-4381-85fa-796d076163aa\"}]}", "hs_task_body": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": null, "hs_task_reminders": "1614319200000", "hs_task_repeat_interval": null, "hs_task_send_default_reminder": null, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "Follow up on Test deal 2", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 756270474, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2021-02-26T06:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2021-02-23T20:25:07.503000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2021-02-23T20:25:07.503Z", "updatedAt": "2023-04-19T14:52:43.485Z", "archived": false, "deals": ["4315375411"], "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "properties_hs_body_preview_html": "\n \n \n Regarding note logged on Tuesday, February 23, 2021 10:25 PM\n \n", "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2021-02-23T20:25:07.503000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-17T18:41:26.373000+00:00", "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": null, "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": false, "properties_hs_lastmodifieddate": "2023-04-19T14:52:43.485000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 11257289597, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[{\"engagementId\":11257289597,\"portalId\":8727216,\"engagementType\":\"TASK\",\"taskType\":\"REMINDER\",\"timestamp\":1614319200000,\"uuid\":\"TASK:e41fd851-f7c7-4381-85fa-796d076163aa\"}]}", "properties_hs_task_body": "Regarding note logged on Tuesday, February 23, 2021 10:25 PM", "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": null, "properties_hs_task_reminders": "1614319200000", "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": null, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "Follow up on Test deal 2", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 756270474, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2021-02-26T06:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2021-02-23T20:25:07.503000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708951556907} +{"stream": "engagements_tasks", "data": {"id": "30652597343", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": null, "hs_body_preview_html": null, "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2023-01-30T23:41:48.834000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-20T15:48:26.766000+00:00", "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": "CRM_UI", "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": null, "hs_lastmodifieddate": "2023-04-04T15:11:47.231000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 30652597343, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "hs_task_body": null, "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": "[]", "hs_task_reminders": null, "hs_task_repeat_interval": null, "hs_task_send_default_reminder": false, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "test", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 507450081, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2023-02-03T07:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2023-01-30T23:41:48.834000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2023-01-30T23:41:48.834Z", "updatedAt": "2023-04-04T15:11:47.231Z", "archived": false, "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": null, "properties_hs_body_preview_html": null, "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2023-01-30T23:41:48.834000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-20T15:48:26.766000+00:00", "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": "CRM_UI", "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": null, "properties_hs_lastmodifieddate": "2023-04-04T15:11:47.231000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 30652597343, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "properties_hs_task_body": null, "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": "[]", "properties_hs_task_reminders": null, "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": false, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "test", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 507450081, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2023-02-03T07:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2023-01-30T23:41:48.834000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708951556909} +{"stream": "engagements_tasks", "data": {"id": "30652613208", "properties": {"hs_all_accessible_team_ids": null, "hs_all_assigned_business_unit_ids": null, "hs_all_owner_ids": "52550153", "hs_all_team_ids": null, "hs_at_mentioned_owner_ids": null, "hs_attachment_ids": null, "hs_body_preview": null, "hs_body_preview_html": null, "hs_body_preview_is_truncated": false, "hs_calendar_event_id": null, "hs_created_by": 12282590, "hs_created_by_user_id": 12282590, "hs_createdate": "2023-01-30T23:51:52.099000+00:00", "hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-19T14:44:21.319000+00:00", "hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_engagement_source": "CRM_UI", "hs_engagement_source_id": null, "hs_follow_up_action": null, "hs_gdpr_deleted": null, "hs_lastmodifieddate": "2023-01-30T23:51:54.343000+00:00", "hs_merged_object_ids": null, "hs_modified_by": 12282590, "hs_msteams_message_id": null, "hs_object_id": 30652613208, "hs_object_source": "CRM_UI", "hs_object_source_detail_1": null, "hs_object_source_detail_2": null, "hs_object_source_detail_3": null, "hs_object_source_id": "userId:12282590", "hs_object_source_label": "CRM_UI", "hs_object_source_user_id": 12282590, "hs_product_name": null, "hs_queue_membership_ids": null, "hs_read_only": null, "hs_repeat_status": null, "hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "hs_task_body": null, "hs_task_completion_count": null, "hs_task_completion_date": null, "hs_task_contact_timezone": null, "hs_task_family": "SALES", "hs_task_for_object_type": "OWNER", "hs_task_is_all_day": false, "hs_task_is_completed": 0, "hs_task_is_completed_call": 0, "hs_task_is_completed_email": 0, "hs_task_is_completed_linked_in": 0, "hs_task_is_completed_sequence": 0, "hs_task_is_overdue": true, "hs_task_is_past_due_date": true, "hs_task_last_contact_outreach": null, "hs_task_last_sales_activity_timestamp": null, "hs_task_missed_due_date": true, "hs_task_missed_due_date_count": 1, "hs_task_ms_teams_payload": null, "hs_task_priority": "NONE", "hs_task_probability_to_complete": null, "hs_task_relative_reminders": "[]", "hs_task_reminders": null, "hs_task_repeat_interval": null, "hs_task_send_default_reminder": false, "hs_task_sequence_enrollment_active": null, "hs_task_sequence_step_enrollment_id": null, "hs_task_sequence_step_order": null, "hs_task_status": "NOT_STARTED", "hs_task_subject": "test", "hs_task_template_id": null, "hs_task_type": "TODO", "hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 597695528, "hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "hs_timestamp": "2023-02-03T07:00:00+00:00", "hs_unique_creation_key": null, "hs_unique_id": null, "hs_updated_by_user_id": 12282590, "hs_user_ids_of_all_notification_followers": null, "hs_user_ids_of_all_notification_unfollowers": null, "hs_user_ids_of_all_owners": "12282590", "hs_was_imported": null, "hubspot_owner_assigneddate": "2023-01-30T23:51:52.099000+00:00", "hubspot_owner_id": "52550153", "hubspot_team_id": null}, "createdAt": "2023-01-30T23:51:52.099Z", "updatedAt": "2023-01-30T23:51:54.343Z", "archived": false, "companies": ["11481383026"], "properties_hs_all_accessible_team_ids": null, "properties_hs_all_assigned_business_unit_ids": null, "properties_hs_all_owner_ids": "52550153", "properties_hs_all_team_ids": null, "properties_hs_at_mentioned_owner_ids": null, "properties_hs_attachment_ids": null, "properties_hs_body_preview": null, "properties_hs_body_preview_html": null, "properties_hs_body_preview_is_truncated": false, "properties_hs_calendar_event_id": null, "properties_hs_created_by": 12282590, "properties_hs_created_by_user_id": 12282590, "properties_hs_createdate": "2023-01-30T23:51:52.099000+00:00", "properties_hs_date_entered_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_entered_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_entered_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": "2024-02-19T14:44:21.319000+00:00", "properties_hs_date_entered_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_entered_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_date_exited_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_date_exited_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_date_exited_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": null, "properties_hs_date_exited_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_date_exited_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_engagement_source": "CRM_UI", "properties_hs_engagement_source_id": null, "properties_hs_follow_up_action": null, "properties_hs_gdpr_deleted": null, "properties_hs_lastmodifieddate": "2023-01-30T23:51:54.343000+00:00", "properties_hs_merged_object_ids": null, "properties_hs_modified_by": 12282590, "properties_hs_msteams_message_id": null, "properties_hs_object_id": 30652613208, "properties_hs_object_source": "CRM_UI", "properties_hs_object_source_detail_1": null, "properties_hs_object_source_detail_2": null, "properties_hs_object_source_detail_3": null, "properties_hs_object_source_id": "userId:12282590", "properties_hs_object_source_label": "CRM_UI", "properties_hs_object_source_user_id": 12282590, "properties_hs_product_name": null, "properties_hs_queue_membership_ids": null, "properties_hs_read_only": null, "properties_hs_repeat_status": null, "properties_hs_scheduled_tasks": "{\"scheduledTasks\":[]}", "properties_hs_task_body": null, "properties_hs_task_completion_count": null, "properties_hs_task_completion_date": null, "properties_hs_task_contact_timezone": null, "properties_hs_task_family": "SALES", "properties_hs_task_for_object_type": "OWNER", "properties_hs_task_is_all_day": false, "properties_hs_task_is_completed": 0, "properties_hs_task_is_completed_call": 0, "properties_hs_task_is_completed_email": 0, "properties_hs_task_is_completed_linked_in": 0, "properties_hs_task_is_completed_sequence": 0, "properties_hs_task_is_overdue": true, "properties_hs_task_is_past_due_date": true, "properties_hs_task_last_contact_outreach": null, "properties_hs_task_last_sales_activity_timestamp": null, "properties_hs_task_missed_due_date": true, "properties_hs_task_missed_due_date_count": 1, "properties_hs_task_ms_teams_payload": null, "properties_hs_task_priority": "NONE", "properties_hs_task_probability_to_complete": null, "properties_hs_task_relative_reminders": "[]", "properties_hs_task_reminders": null, "properties_hs_task_repeat_interval": null, "properties_hs_task_send_default_reminder": false, "properties_hs_task_sequence_enrollment_active": null, "properties_hs_task_sequence_step_enrollment_id": null, "properties_hs_task_sequence_step_order": null, "properties_hs_task_status": "NOT_STARTED", "properties_hs_task_subject": "test", "properties_hs_task_template_id": null, "properties_hs_task_type": "TODO", "properties_hs_time_in_60b5c368_04c4_4d32_9b4a_457e159f49b7_13292096": null, "properties_hs_time_in_61bafb31_e7fa_46ed_aaa9_1322438d6e67_1866552342": null, "properties_hs_time_in_af0e6a5c_2ea3_4c72_b69f_7c6cb3fdb591_1652950531": 597695528, "properties_hs_time_in_dd5826e4_c976_4654_a527_b59ada542e52_2144133616": null, "properties_hs_time_in_fc8148fb_3a2d_4b59_834e_69b7859347cb_1813133675": null, "properties_hs_timestamp": "2023-02-03T07:00:00+00:00", "properties_hs_unique_creation_key": null, "properties_hs_unique_id": null, "properties_hs_updated_by_user_id": 12282590, "properties_hs_user_ids_of_all_notification_followers": null, "properties_hs_user_ids_of_all_notification_unfollowers": null, "properties_hs_user_ids_of_all_owners": "12282590", "properties_hs_was_imported": null, "properties_hubspot_owner_assigneddate": "2023-01-30T23:51:52.099000+00:00", "properties_hubspot_owner_id": "52550153", "properties_hubspot_team_id": null}, "emitted_at": 1708951556910} {"stream": "forms", "data": {"id": "01ba116c-f3a8-4957-8884-ff0c4420af76", "name": "DemoForm", "createdAt": "2021-01-14T14:44:48.278Z", "updatedAt": "2021-01-14T14:44:48.278Z", "archived": false, "fieldGroups": [{"groupType": "default_group", "richTextType": "text", "fields": [{"objectTypeId": "0-1", "name": "firstname", "label": "First Name", "required": false, "hidden": false, "fieldType": "single_line_text"}]}, {"groupType": "default_group", "richTextType": "text", "fields": [{"objectTypeId": "0-1", "name": "lastname", "label": "Last Name", "required": false, "hidden": false, "fieldType": "single_line_text"}]}, {"groupType": "default_group", "richTextType": "text", "fields": [{"objectTypeId": "0-1", "name": "adress_1", "label": "Adress 1", "required": false, "hidden": false, "fieldType": "single_line_text"}]}], "configuration": {"language": "en", "cloneable": true, "postSubmitAction": {"type": "thank_you", "value": ""}, "editable": true, "archivable": true, "recaptchaEnabled": false, "notifyContactOwner": false, "notifyRecipients": [], "createNewContactForNewEmail": false, "prePopulateKnownValues": true, "allowLinkToResetKnownValues": false, "lifecycleStages": []}, "displayOptions": {"renderRawHtml": false, "theme": "default_style", "submitButtonText": "Submit", "style": {"fontFamily": "arial, helvetica, sans-serif", "backgroundWidth": "100%", "labelTextColor": "#33475b", "labelTextSize": "11px", "helpTextColor": "#7C98B6", "helpTextSize": "11px", "legalConsentTextColor": "#33475b", "legalConsentTextSize": "14px", "submitColor": "#ff7a59", "submitAlignment": "left", "submitFontColor": "#ffffff", "submitSize": "12px"}, "cssClass": null}, "legalConsentOptions": {"type": "none"}, "formType": "hubspot"}, "emitted_at": 1697714221520} {"stream": "forms", "data": {"id": "03e69987-1dcb-4d55-9cb6-d3812ac00ee6", "name": "New form 93", "createdAt": "2023-02-13T16:56:33.108Z", "updatedAt": "2023-02-13T16:56:33.108Z", "archived": false, "fieldGroups": [{"groupType": "default_group", "richTextType": "text", "fields": [{"objectTypeId": "0-1", "name": "email", "label": "Email", "required": true, "hidden": false, "fieldType": "email", "validation": {"blockedEmailDomains": [], "useDefaultBlockList": false}}]}], "configuration": {"language": "en", "cloneable": true, "postSubmitAction": {"type": "thank_you", "value": "Thanks for submitting the form."}, "editable": true, "archivable": true, "recaptchaEnabled": false, "notifyContactOwner": false, "notifyRecipients": ["12282590"], "createNewContactForNewEmail": false, "prePopulateKnownValues": true, "allowLinkToResetKnownValues": false, "lifecycleStages": []}, "displayOptions": {"renderRawHtml": false, "theme": "default_style", "submitButtonText": "Submit", "style": {"fontFamily": "arial, helvetica, sans-serif", "backgroundWidth": "100%", "labelTextColor": "#33475b", "labelTextSize": "14px", "helpTextColor": "#7C98B6", "helpTextSize": "11px", "legalConsentTextColor": "#33475b", "legalConsentTextSize": "14px", "submitColor": "#ff7a59", "submitAlignment": "left", "submitFontColor": "#ffffff", "submitSize": "12px"}, "cssClass": "hs-form stacked"}, "legalConsentOptions": {"type": "implicit_consent_to_process", "communicationConsentText": "integrationtest is committed to protecting and respecting your privacy, and we\u2019ll only use your personal information to administer your account and to provide the products and services you requested from us. From time to time, we would like to contact you about our products and services, as well as other content that may be of interest to you. If you consent to us contacting you for this purpose, please tick below to say how you would like us to contact you:", "communicationsCheckboxes": [{"required": false, "subscriptionTypeId": 23704464, "label": "I agree to receive other communications from [MAIN] integration test account."}], "privacyText": "You may unsubscribe from these communications at any time. For more information on how to unsubscribe, our privacy practices, and how we are committed to protecting and respecting your privacy, please review our Privacy Policy.", "consentToProcessText": "By clicking submit below, you consent to allow integrationtest to store and process the personal information submitted above to provide you the content requested."}, "formType": "hubspot"}, "emitted_at": 1697714221521} {"stream": "forms", "data": {"id": "0a7fd84f-471e-444a-a4e0-ca36d39f8af7", "name": "New form 27", "createdAt": "2023-02-13T16:45:22.640Z", "updatedAt": "2023-02-13T16:45:22.640Z", "archived": false, "fieldGroups": [{"groupType": "default_group", "richTextType": "text", "fields": [{"objectTypeId": "0-1", "name": "email", "label": "Email", "required": true, "hidden": false, "fieldType": "email", "validation": {"blockedEmailDomains": [], "useDefaultBlockList": false}}]}], "configuration": {"language": "en", "cloneable": true, "postSubmitAction": {"type": "thank_you", "value": "Thanks for submitting the form."}, "editable": true, "archivable": true, "recaptchaEnabled": false, "notifyContactOwner": false, "notifyRecipients": ["12282590"], "createNewContactForNewEmail": false, "prePopulateKnownValues": true, "allowLinkToResetKnownValues": false, "lifecycleStages": []}, "displayOptions": {"renderRawHtml": false, "theme": "default_style", "submitButtonText": "Submit", "style": {"fontFamily": "arial, helvetica, sans-serif", "backgroundWidth": "100%", "labelTextColor": "#33475b", "labelTextSize": "14px", "helpTextColor": "#7C98B6", "helpTextSize": "11px", "legalConsentTextColor": "#33475b", "legalConsentTextSize": "14px", "submitColor": "#ff7a59", "submitAlignment": "left", "submitFontColor": "#ffffff", "submitSize": "12px"}, "cssClass": "hs-form stacked"}, "legalConsentOptions": {"type": "implicit_consent_to_process", "communicationConsentText": "integrationtest is committed to protecting and respecting your privacy, and we\u2019ll only use your personal information to administer your account and to provide the products and services you requested from us. From time to time, we would like to contact you about our products and services, as well as other content that may be of interest to you. If you consent to us contacting you for this purpose, please tick below to say how you would like us to contact you:", "communicationsCheckboxes": [{"required": false, "subscriptionTypeId": 23704464, "label": "I agree to receive other communications from [MAIN] integration test account."}], "privacyText": "You may unsubscribe from these communications at any time. For more information on how to unsubscribe, our privacy practices, and how we are committed to protecting and respecting your privacy, please review our Privacy Policy.", "consentToProcessText": "By clicking submit below, you consent to allow integrationtest to store and process the personal information submitted above to provide you the content requested."}, "formType": "hubspot"}, "emitted_at": 1697714221522} diff --git a/airbyte-integrations/connectors/source-hubspot/pyproject.toml b/airbyte-integrations/connectors/source-hubspot/pyproject.toml index 56e1120e9a28..21bb9a12a9f4 100644 --- a/airbyte-integrations/connectors/source-hubspot/pyproject.toml +++ b/airbyte-integrations/connectors/source-hubspot/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "3.1.1" +version = "3.2.0" name = "source-hubspot" description = "Source implementation for HubSpot." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index 9304a709827f..37cdc49c57c9 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -328,7 +328,7 @@ The connector is restricted by normal HubSpot [rate limitations](https://legacyd | 3.0.1 | 2024-01-29 | [34635](https://github.com/airbytehq/airbyte/pull/34635) | Fix pagination for `CompaniesPropertyHistory` stream | | 3.0.0 | 2024-01-25 | [34492](https://github.com/airbytehq/airbyte/pull/34492) | Update `marketing_emails` stream schema | | 2.0.2 | 2023-12-15 | [33844](https://github.com/airbytehq/airbyte/pull/33844) | Make property_history PK combined to support Incremental/Deduped sync type | -| 2.0.1 | 2023-12-15 | [33527](https://github.com/airbytehq/airbyte/pull/33527) | Make query string calculated correctly for ProertyHistory streams to avoid 414 HTTP Errors | +| 2.0.1 | 2023-12-15 | [33527](https://github.com/airbytehq/airbyte/pull/33527) | Make query string calculated correctly for PropertyHistory streams to avoid 414 HTTP Errors | | 2.0.0 | 2023-12-08 | [33266](https://github.com/airbytehq/airbyte/pull/33266) | Add ContactsPropertyHistory, CompaniesPropertyHistory, DealsPropertyHistory streams | | 1.9.0 | 2023-12-04 | [33042](https://github.com/airbytehq/airbyte/pull/33042) | Add Web Analytics streams | | 1.8.0 | 2023-11-23 | [32778](https://github.com/airbytehq/airbyte/pull/32778) | Extend `PropertyHistory` stream to support incremental sync | From 5fc6ca213121305c5413b5d288e4205d8b4fddce Mon Sep 17 00:00:00 2001 From: Daryna Ishchenko <80129833+darynaishchenko@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:00:01 +0200 Subject: [PATCH 73/74] :hospital: Source Mixpanel: updated version in pyproject.toml (#35537) --- airbyte-integrations/connectors/source-mixpanel/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/source-mixpanel/pyproject.toml b/airbyte-integrations/connectors/source-mixpanel/pyproject.toml index a958e0159aa4..bb4f7f27ce3f 100644 --- a/airbyte-integrations/connectors/source-mixpanel/pyproject.toml +++ b/airbyte-integrations/connectors/source-mixpanel/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.0.2" +version = "2.1.0" name = "source-mixpanel" description = "Source implementation for Mixpanel." authors = [ "Airbyte ",] From f5094041bebb80cd6602a98829c19a7515276ed3 Mon Sep 17 00:00:00 2001 From: Baz Date: Mon, 26 Feb 2024 18:05:36 +0200 Subject: [PATCH 74/74] =?UTF-8?q?=F0=9F=90=9B=20Source=20Shopify:=20Migrat?= =?UTF-8?q?e=20from=20=20`REST`=20>=20`GraphQL=20BULK=20Operations`=20wher?= =?UTF-8?q?e=20possible,=20fixed=20`STATE`=20collisions=20for=20`sub-strea?= =?UTF-8?q?ms`=20(#32345)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connectors/source-shopify/README.md | 2 +- .../source-shopify/acceptance-test-config.yml | 41 +- .../integration_tests/abnormal_state.json | 16 +- .../integration_tests/expected_records.jsonl | 176 +- ...ed_records_transactions_with_user_id.jsonl | 96 + .../integration_tests/state.json | 6 +- .../connectors/source-shopify/metadata.yaml | 31 +- .../connectors/source-shopify/poetry.lock | 22 +- .../connectors/source-shopify/pyproject.toml | 3 +- .../source-shopify/source_shopify/auth.py | 1 - .../schemas/customer_address.json | 4 + .../source_shopify/schemas/customers.json | 3 + .../schemas/discount_codes.json | 9 + .../schemas/fulfillment_orders.json | 34 +- .../source_shopify/schemas/fulfillments.json | 227 + .../source_shopify/schemas/order_refunds.json | 91 +- .../source_shopify/schemas/orders.json | 224 + .../source_shopify/schemas/products.json | 9 + .../source_shopify/schemas/transactions.json | 64 +- .../source-shopify/source_shopify/scopes.py | 157 + .../shopify_graphql/bulk/exceptions.py | 40 + .../shopify_graphql/bulk/job.py | 262 + .../shopify_graphql/bulk/query.py | 1484 +++ .../shopify_graphql/bulk/record.py | 154 + .../shopify_graphql/bulk/tools.py | 83 + .../{ => shopify_graphql}/graphql.py | 5 +- .../schema.py} | 10330 +++++++++++----- .../source-shopify/source_shopify/source.py | 1065 +- .../source-shopify/source_shopify/spec.json | 12 + .../source_shopify/streams/base_streams.py | 722 ++ .../source_shopify/streams/streams.py | 388 + .../source_shopify/transform.py | 3 + .../source-shopify/source_shopify/utils.py | 119 +- .../source-shopify/unit_tests/conftest.py | 800 ++ .../unit_tests/graphql_bulk/test_job.py | 265 + .../unit_tests/graphql_bulk/test_query.py | 209 + .../unit_tests/graphql_bulk/test_record.py | 198 + .../unit_tests/graphql_bulk/test_tools.py | 54 + .../unit_tests/test_cached_stream_state.py | 2 +- .../unit_tests/test_deleted_events_stream.py | 25 +- .../unit_tests/test_graphql_products.py | 2 +- .../source-shopify/unit_tests/test_source.py | 95 +- .../source-shopify/unit_tests/unit_test.py | 67 +- .../sources/shopify-migrations.md | 38 + docs/integrations/sources/shopify.md | 73 +- 45 files changed, 13306 insertions(+), 4405 deletions(-) create mode 100644 airbyte-integrations/connectors/source-shopify/integration_tests/expected_records_transactions_with_user_id.jsonl create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/scopes.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/exceptions.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/job.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/query.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/record.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/tools.py rename airbyte-integrations/connectors/source-shopify/source_shopify/{ => shopify_graphql}/graphql.py (97%) rename airbyte-integrations/connectors/source-shopify/source_shopify/{shopify_schema.py => shopify_graphql/schema.py} (78%) create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/streams/base_streams.py create mode 100644 airbyte-integrations/connectors/source-shopify/source_shopify/streams/streams.py create mode 100644 airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_job.py create mode 100644 airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_query.py create mode 100644 airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_record.py create mode 100644 airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_tools.py diff --git a/airbyte-integrations/connectors/source-shopify/README.md b/airbyte-integrations/connectors/source-shopify/README.md index 86eeb80672b5..2162414e3611 100644 --- a/airbyte-integrations/connectors/source-shopify/README.md +++ b/airbyte-integrations/connectors/source-shopify/README.md @@ -30,7 +30,7 @@ See `sample_files/sample_config.json` for a sample config file. poetry run source-shopify spec poetry run source-shopify check --config secrets/config.json poetry run source-shopify discover --config secrets/config.json -poetry run source-shopify read --config secrets/config.json --catalog sample_files/configured_catalog.json +poetry run source-shopify read --config secrets/config.json --catalog integration_tests/configured_catalog.json ``` ### Running unit tests diff --git a/airbyte-integrations/connectors/source-shopify/acceptance-test-config.yml b/airbyte-integrations/connectors/source-shopify/acceptance-test-config.yml index bb0b185cfeda..c38d1f41afaa 100644 --- a/airbyte-integrations/connectors/source-shopify/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-shopify/acceptance-test-config.yml @@ -24,8 +24,47 @@ acceptance_tests: discovery: tests: - config_path: "secrets/config.json" + backward_compatibility_tests_config: + # The cursor field for `fulfillments` stream has changed from `id` to `updated_at` + disable_for_version: "1.1.8" basic_read: tests: + - config_path: "secrets/config_transactions_with_user_id.json" + timeout_seconds: 4800 + expect_records: + path: "integration_tests/expected_records_transactions_with_user_id.jsonl" + empty_streams: + - name: abandoned_checkouts + bypass_reason: The stream holds data up to 1 month then records are removed by Shopify. + - name: balance_transactions + bypass_reason: The stream requires real purchases to fill in the data. + - name: customer_saved_search + bypass_reason: The stream is not available for our sandbox. + - name: disputes + bypass_reason: The stream requires real purchases to fill in the data. + ignored_fields: + products: + - name: variants/*/updated_at + bypass_reason: Value can change as the account data is not frozen + - name: image/src + bypass_reason: May contain dynamically changed URL params + - name: image/updated_at + bypass_reason: Value can change as the account data is not frozen + - name: images/*/src + bypass_reason: May contain dynamically changed URL params + - name: images/*/updated_at + bypass_reason: Value can change as the account data is not frozen + products_graph_ql: + - name: onlineStorePreviewUrl + bypass_reason: Autogenerated floating URL values + product_variants: + - name: updated_at + bypass_reason: Value can change as the account data is not frozen + product_images: + - name: src + bypass_reason: May contain dynamically changed URL params + - name: updated_at + bypass_reason: Value can change as the account data is not frozen - config_path: "secrets/config.json" timeout_seconds: 4800 expect_records: @@ -68,7 +107,7 @@ acceptance_tests: configured_catalog_path: "integration_tests/configured_catalog.json" future_state: future_state_path: "integration_tests/abnormal_state.json" - timeout_seconds: 14400 + timeout_seconds: 7200 full_refresh: tests: - config_path: "secrets/config.json" diff --git a/airbyte-integrations/connectors/source-shopify/integration_tests/abnormal_state.json b/airbyte-integrations/connectors/source-shopify/integration_tests/abnormal_state.json index 29376d5432ca..00af9172d88d 100644 --- a/airbyte-integrations/connectors/source-shopify/integration_tests/abnormal_state.json +++ b/airbyte-integrations/connectors/source-shopify/integration_tests/abnormal_state.json @@ -158,6 +158,17 @@ } } }, + { + "type": "STREAM", + "stream": { + "stream_state": { + "created_at": "2027-07-11T13:07:45-07:00" + }, + "stream_descriptor": { + "name": "transactions_graphql" + } + } + }, { "type": "STREAM", "stream": { @@ -253,7 +264,7 @@ "deleted_at": "2027-07-11T13:07:45-07:00" } }, - "id": 99999999999999 + "updated_at": "2027-07-11T13:07:45-07:00" }, "stream_descriptor": { "name": "fulfillment_orders" @@ -449,7 +460,8 @@ "deleted": { "deleted_at": "2027-07-11T13:07:45-07:00" } - } + }, + "updated_at": "2027-07-11T13:07:45-07:00" }, "stream_descriptor": { "name": "product_variants" diff --git a/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records.jsonl index 22205205125d..d43ad7bf0369 100644 --- a/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records.jsonl @@ -1,80 +1,96 @@ -{"stream": "articles", "data": {"id": 558137508029, "title": "My new Article title", "created_at": "2022-10-07T16:09:02-07:00", "body_html": "

I like articles

\n

Yea, I like posting them through REST.

", "blog_id": 80417685693, "author": "John Smith", "user_id": null, "published_at": "2011-03-24T08:45:47-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "summary_html": null, "template_suffix": null, "handle": "my-new-article-title", "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558137508029", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194671409} -{"stream": "articles", "data": {"id": 558627979453, "title": "Test Blog Post", "created_at": "2023-04-14T03:19:02-07:00", "body_html": "Test Blog Post 1", "blog_id": 80417685693, "author": "Airbyte Airbyte", "user_id": "74861019325", "published_at": null, "updated_at": "2023-04-14T03:19:18-07:00", "summary_html": "", "template_suffix": "", "handle": "test-blog-post", "tags": "Has Been Tagged", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558627979453", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194671410} -{"stream": "articles", "data": {"id": 558999371965, "deleted_at": "2023-09-05T13:50:04-07:00", "updated_at": "2023-09-05T13:50:04-07:00", "deleted_message": "Online Store deleted an article: Test Article 1.", "deleted_description": "Online Store deleted an article: Test Article 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194671993} -{"stream": "blogs", "data": {"id": 80417685693, "handle": "news", "title": "News", "updated_at": "2023-09-05T14:02:00-07:00", "commentable": "no", "feedburner": null, "feedburner_location": null, "created_at": "2021-06-22T18:00:25-07:00", "template_suffix": null, "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreBlog/80417685693", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194674015} -{"stream": "blogs", "data": {"id": 85733114045, "deleted_at": "2023-09-06T03:30:22-07:00", "updated_at": "2023-09-06T03:30:22-07:00", "deleted_message": "Online Store deleted a blog: Test Blog 1.", "deleted_description": "Online Store deleted a blog: Test Blog 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194674556} -{"stream": "collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T07:06:59-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-06-22T18:00:25-07:00", "sort_order": "best-selling", "template_suffix": "", "products_count": 1, "collection_type": "custom", "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194676559} -{"stream": "collects", "data": {"id": 29427031703741, "collection_id": 270889287869, "product_id": 6796220989629, "created_at": "2021-07-19T07:01:36-07:00", "updated_at": "2022-03-06T14:12:21-08:00", "position": 2, "sort_value": "0000000002", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194677532} -{"stream": "custom_collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T07:06:59-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-06-22T18:00:25-07:00", "sort_order": "best-selling", "template_suffix": "", "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194678538} -{"stream": "custom_collections", "data": {"id": 294253822141, "deleted_at": "2023-09-06T03:34:39-07:00", "updated_at": "2023-09-06T03:34:39-07:00", "deleted_message": "Airbyte Airbyte deleted a collection.", "deleted_description": "Airbyte Airbyte deleted a collection.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194679372} -{"stream": "customers", "data": {"id": 6569096478909, "email": "test@test.com", "accepts_marketing": true, "created_at": "2023-04-13T02:30:04-07:00", "updated_at": "2023-04-24T06:53:48-07:00", "first_name": "New Test", "last_name": "Customer", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": "updated_mon_24.04.2023", "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": "+380639379992", "addresses": [{"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}], "accepts_marketing_updated_at": "2023-04-13T02:30:04-07:00", "marketing_opt_in_level": "single_opt_in", "tax_exemptions": "[]", "email_marketing_consent": {"state": "subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": "2023-04-13T02:30:04-07:00"}, "sms_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null, "consent_collected_from": "SHOPIFY"}, "admin_graphql_api_id": "gid://shopify/Customer/6569096478909", "default_address": {"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194680438} -{"stream": "customers", "data": {"id": 6676027932861, "email": "marcos@airbyte.io", "accepts_marketing": false, "created_at": "2023-07-11T13:07:45-07:00", "updated_at": "2023-07-11T13:07:45-07:00", "first_name": "MArcos", "last_name": "Millnitz", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": null, "addresses": [{"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}], "accepts_marketing_updated_at": "2023-07-11T13:07:45-07:00", "marketing_opt_in_level": null, "tax_exemptions": "[]", "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "admin_graphql_api_id": "gid://shopify/Customer/6676027932861", "default_address": {"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194680439} -{"stream": "discount_codes", "data": {"id": 11539415990461, "price_rule_id": 945000284349, "code": "updated_mon_24.04.2023", "usage_count": 0, "created_at": "2021-07-07T07:23:11-07:00", "updated_at": "2023-04-24T05:52:22-07:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194682519} -{"stream": "draft_orders", "data": {"id": 929019691197, "note": "updated_mon_24.04.2023", "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2022-02-22T03:23:19-08:00", "updated_at": "2023-04-24T07:18:06-07:00", "tax_exempt": false, "completed_at": null, "name": "#D21", "status": "open", "line_items": [{"id": 58117295538365, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 2, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295538365"}, {"id": 58117295571133, "variant_id": null, "product_id": null, "title": "Test Item", "variant_title": null, "sku": null, "vendor": null, "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 1000, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 0.17}], "applied_discount": null, "name": "Test Item", "properties": [], "custom": true, "price": 1.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295571133"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/12893992cc01fc67935ab014fcf9300f", "applied_discount": null, "order_id": null, "shipping_line": {"title": "Test Shipping Fee", "custom": true, "handle": null, "price": 3.0}, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}, {"rate": 0.2, "title": "PDV", "price": 0.17}], "tags": "", "note_attributes": [], "total_price": "42.00", "subtotal_price": "39.00", "total_tax": "6.50", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/929019691197", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194685211} -{"stream": "draft_orders", "data": {"id": 988639920317, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2023-04-24T11:00:01-07:00", "updated_at": "2023-04-24T11:00:09-07:00", "tax_exempt": false, "completed_at": "2023-04-24T11:00:09-07:00", "name": "#D29", "status": "completed", "line_items": [{"id": 58121808019645, "variant_id": 41561961824445, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Test Variant 2", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Test Variant 2", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58121808019645"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/95271a5eeb083c831f76a98fa3712f89", "applied_discount": null, "order_id": 5033391718589, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "tags": "", "note_attributes": [], "total_price": "19.00", "subtotal_price": "19.00", "total_tax": "3.17", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/988639920317", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194685213} -{"stream": "draft_orders", "data": {"id": 997801689277, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2023-07-11T12:57:53-07:00", "updated_at": "2023-07-11T12:57:55-07:00", "tax_exempt": false, "completed_at": null, "name": "#D30", "status": "open", "line_items": [{"id": 58159126905021, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58159126905021"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/a98bc7e113733d6faa36c198cf6c7c1a", "applied_discount": null, "order_id": null, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "tags": "", "note_attributes": [], "total_price": "19.00", "subtotal_price": "19.00", "total_tax": "3.17", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/997801689277", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194685214} -{"stream": "fulfillment_orders", "data": {"id": 5558588309693, "shop_id": 58033176765, "order_id": 4554821468349, "assigned_location_id": 63590301885, "request_status": "unsubmitted", "status": "closed", "supported_actions": [], "destination": null, "line_items": [{"id": 11564232016061, "shop_id": 58033176765, "fulfillment_order_id": 5558588309693, "quantity": 1, "line_item_id": 11406125564093, "inventory_item_id": 42185212592317, "fulfillable_quantity": 0, "variant_id": 40090597884093}], "fulfill_at": "2022-06-15T05:00:00-07:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2022-06-15T05:16:54-07:00", "updated_at": "2022-06-15T05:16:55-07:00", "delivery_method": {"id": 119732437181, "method_type": "none", "min_delivery_date_time": null, "max_delivery_date_time": null}, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "location_id": 63590301885, "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100"}, "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194687309} -{"stream": "fulfillment_orders", "data": {"id": 5138290671805, "shop_id": 58033176765, "order_id": 4147980107965, "assigned_location_id": 63590301885, "request_status": "unsubmitted", "status": "closed", "supported_actions": [], "destination": {"id": 5183946588349, "address1": "San Francisco", "address2": "10", "city": "San Francisco", "company": "Umbrella LLC", "country": "United States", "email": "airbyte@airbyte.com", "first_name": "John", "last_name": "Doe", "phone": "", "province": "California", "zip": "91326"}, "line_items": [{"id": 10713758531773, "shop_id": 58033176765, "fulfillment_order_id": 5138290671805, "quantity": 1, "line_item_id": 10576771317949, "inventory_item_id": 42185195290813, "fulfillable_quantity": 0, "variant_id": 40090580615357}], "fulfill_at": null, "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2021-09-19T09:08:23-07:00", "updated_at": "2021-09-19T09:08:23-07:00", "delivery_method": null, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "location_id": 63590301885, "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100"}, "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194687822} -{"stream": "fulfillment_orders", "data": {"id": 4919375659197, "shop_id": 58033176765, "order_id": 3935377129661, "assigned_location_id": 63590301885, "request_status": "unsubmitted", "status": "closed", "supported_actions": [], "destination": null, "line_items": [{"id": 10251692081341, "shop_id": 58033176765, "fulfillment_order_id": 4919375659197, "quantity": 1, "line_item_id": 10130216452285, "inventory_item_id": 42185218719933, "fulfillable_quantity": 1, "variant_id": 40090604011709}], "fulfill_at": null, "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2021-07-02T00:51:51-07:00", "updated_at": "2021-09-21T05:31:59-07:00", "delivery_method": null, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "location_id": 63590301885, "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100"}, "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194688332} -{"stream": "fulfillments", "data": {"id": 4075788501181, "order_id": 4554821468349, "status": "success", "created_at": "2022-06-15T05:16:55-07:00", "service": "manual", "updated_at": "2022-06-15T05:16:55-07:00", "tracking_company": null, "shipment_status": null, "location_id": 63590301885, "origin_address": null, "line_items": [{"id": 11406125564093, "variant_id": 40090597884093, "title": "All Black Sneaker Right Foot", "quantity": 1, "sku": "", "variant_title": "ivory", "vendor": "Becker - Moore", "fulfillment_service": "manual", "product_id": 6796226560189, "requires_shipping": false, "taxable": true, "gift_card": false, "name": "All Black Sneaker Right Foot - ivory", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 0, "price": "59.00", "total_discount": "0.00", "fulfillment_status": "fulfilled", "price_set": {"shop_money": {"amount": "59.00", "currency_code": "USD"}, "presentment_money": {"amount": "59.00", "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "discount_allocations": [{"amount": "1.77", "discount_application_index": 0, "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}}], "origin_location": {"id": 3007664259261, "country_code": "UA", "province_code": "", "name": "airbyte integration test", "address1": "Heroiv UPA 72", "address2": "", "city": "Lviv", "zip": "30100"}, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "duties": [], "tax_lines": [], "fulfillment_line_item_id": 9633709097149}], "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "receipt": {}, "name": "#1136.1", "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194691604} -{"stream": "fulfillments", "data": {"id": 3693416710333, "order_id": 4147980107965, "status": "success", "created_at": "2021-09-19T09:08:23-07:00", "service": "manual", "updated_at": "2022-02-22T00:35:47-08:00", "tracking_company": "Amazon Logistics US", "shipment_status": null, "location_id": 63590301885, "origin_address": null, "line_items": [{"id": 10576771317949, "variant_id": 40090580615357, "title": "Red & Silver Fishing Lure", "quantity": 1, "sku": "", "variant_title": "Plastic", "vendor": "Harris - Hamill", "fulfillment_service": "manual", "product_id": 6796218302653, "requires_shipping": true, "taxable": true, "gift_card": false, "name": "Red & Silver Fishing Lure - Plastic", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 285, "price": "27.00", "total_discount": "0.00", "fulfillment_status": "fulfilled", "price_set": {"shop_money": {"amount": "27.00", "currency_code": "USD"}, "presentment_money": {"amount": "27.00", "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "discount_allocations": [], "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "duties": [], "tax_lines": [], "fulfillment_line_item_id": 8852381401277}], "tracking_number": "123456", "tracking_numbers": ["123456"], "tracking_url": "https://track.amazon.com/tracking/123456", "tracking_urls": ["https://track.amazon.com/tracking/123456"], "receipt": {}, "name": "#1121.1", "admin_graphql_api_id": "gid://shopify/Fulfillment/3693416710333", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194692148} -{"stream": "fulfillments", "data": {"id": 4465911431357, "order_id": 5033391718589, "status": "success", "created_at": "2023-04-24T11:00:09-07:00", "service": "manual", "updated_at": "2023-04-24T11:00:09-07:00", "tracking_company": null, "shipment_status": null, "location_id": 63590301885, "origin_address": null, "line_items": [{"id": 12247585521853, "variant_id": 41561961824445, "title": "4 Ounce Soy Candle", "quantity": 1, "sku": "", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "fulfillment_service": "manual", "product_id": 6796220989629, "requires_shipping": true, "taxable": true, "gift_card": false, "name": "4 Ounce Soy Candle - Test Variant 2", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 112, "price": "19.00", "total_discount": "0.00", "fulfillment_status": "fulfilled", "price_set": {"shop_money": {"amount": "19.00", "currency_code": "USD"}, "presentment_money": {"amount": "19.00", "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "discount_allocations": [], "origin_location": {"id": 3000230707389, "country_code": "UA", "province_code": "", "name": "Heroiv UPA 72", "address1": "Heroiv UPA 72", "address2": "", "city": "Lviv", "zip": "30100"}, "admin_graphql_api_id": "gid://shopify/LineItem/12247585521853", "duties": [], "tax_lines": [{"price": 3.17, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": "3.17", "currency_code": "USD"}, "presentment_money": {"amount": "3.17", "currency_code": "USD"}}, "channel_liable": null}], "fulfillment_line_item_id": 10383179514045}], "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "receipt": {}, "name": "#1145.1", "admin_graphql_api_id": "gid://shopify/Fulfillment/4465911431357", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194693123} -{"stream": "inventory_items", "data": {"id": 42185200631997, "sku": "", "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2022-02-22T00:40:19-08:00", "requires_shipping": true, "cost": 19.0, "country_code_of_origin": null, "province_code_of_origin": null, "harmonized_system_code": null, "tracked": true, "country_harmonized_system_codes": [], "admin_graphql_api_id": "gid://shopify/InventoryItem/42185200631997", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194695452} -{"stream": "inventory_items", "data": {"id": 43653682495677, "sku": "", "created_at": "2022-03-06T14:09:20-08:00", "updated_at": "2022-03-06T14:09:20-08:00", "requires_shipping": true, "cost": 19.0, "country_code_of_origin": null, "province_code_of_origin": null, "harmonized_system_code": null, "tracked": true, "country_harmonized_system_codes": [], "admin_graphql_api_id": "gid://shopify/InventoryItem/43653682495677", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194695454} -{"stream": "inventory_items", "data": {"id": 43653688524989, "sku": "", "created_at": "2022-03-06T14:12:20-08:00", "updated_at": "2022-03-06T14:12:20-08:00", "requires_shipping": true, "cost": 19.0, "country_code_of_origin": null, "province_code_of_origin": null, "harmonized_system_code": null, "tracked": true, "country_harmonized_system_codes": [], "admin_graphql_api_id": "gid://shopify/InventoryItem/43653688524989", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194695454} -{"stream": "inventory_levels", "data": {"inventory_item_id": 42185194668221, "location_id": 63590301885, "available": 12, "updated_at": "2021-06-22T18:09:27-07:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185194668221", "shop_url": "airbyte-integration-test", "id": "63590301885|42185194668221"}, "emitted_at": 1697194698578} -{"stream": "inventory_levels", "data": {"inventory_item_id": 42185194700989, "location_id": 63590301885, "available": 3, "updated_at": "2021-06-22T18:09:27-07:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185194700989", "shop_url": "airbyte-integration-test", "id": "63590301885|42185194700989"}, "emitted_at": 1697194698579} -{"stream": "inventory_levels", "data": {"inventory_item_id": 42185194733757, "location_id": 63590301885, "available": 38, "updated_at": "2021-06-22T18:09:27-07:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185194733757", "shop_url": "airbyte-integration-test", "id": "63590301885|42185194733757"}, "emitted_at": 1697194698579} -{"stream":"locations","data":{"id":63590301885,"name":"Heroiv UPA 72","address1":"Heroiv UPA 72","address2":"","city":"Lviv","zip":"30100","province":null,"country":"UA","phone":"","created_at":"2021-06-22T18:00:29-07:00","updated_at":"2023-11-28T07:08:27-08:00","country_code":"UA","country_name":"Ukraine","province_code":null,"legacy":false,"active":true,"admin_graphql_api_id":"gid://shopify/Location/63590301885","localized_country_name":"Ukraine","localized_province_name":null,"shop_url":"airbyte-integration-test"},"emitted_at":1704314548257} -{"stream": "metafield_articles", "data": {"id": 21519818162365, "namespace": "global", "key": "new", "value": "newvalue", "description": null, "owner_id": 558137508029, "created_at": "2022-10-07T16:09:02-07:00", "updated_at": "2022-10-07T16:09:02-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519818162365", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194703693} -{"stream": "metafield_articles", "data": {"id": 22365709992125, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Article Metafield", "description": null, "owner_id": 558137508029, "created_at": "2023-04-14T03:18:26-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365709992125", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194703694} -{"stream": "metafield_articles", "data": {"id": 22365710352573, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Blog Post Metafiled", "description": null, "owner_id": 558627979453, "created_at": "2023-04-14T03:19:18-07:00", "updated_at": "2023-04-14T03:19:18-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710352573", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194704159} -{"stream": "metafield_blogs", "data": {"id": 21519428255933, "namespace": "some_fields", "key": "sponsor", "value": "Shopify", "description": null, "owner_id": 80417685693, "created_at": "2022-10-07T06:05:23-07:00", "updated_at": "2022-10-07T06:05:23-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519428255933", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194706701} -{"stream": "metafield_blogs", "data": {"id": 22365710745789, "namespace": "custom", "key": "test_blog_metafield", "value": "Test Blog Metafield", "description": null, "owner_id": 80417685693, "created_at": "2023-04-14T03:20:20-07:00", "updated_at": "2023-04-14T03:20:20-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710745789", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194706702} -{"stream": "metafield_collections", "data": {"id": 21520343367869, "namespace": "my_fields", "key": "discount", "value": "25%", "description": null, "owner_id": 270889287869, "created_at": "2022-10-08T04:44:51-07:00", "updated_at": "2022-10-08T04:44:51-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21520343367869", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194709216} -{"stream": "metafield_collections", "data": {"id": 22365707174077, "namespace": "custom", "key": "test_collection_metafield", "value": "Test Collection Metafield", "description": null, "owner_id": 270889287869, "created_at": "2023-04-14T03:15:30-07:00", "updated_at": "2023-04-14T03:15:30-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365707174077", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194709218} -{"stream": "metafield_customers", "data": {"id": 22346893361341, "namespace": "custom", "key": "test_definition_list_1", "value": "Teste\n", "description": null, "owner_id": 6569096478909, "created_at": "2023-04-13T04:50:10-07:00", "updated_at": "2023-04-13T04:50:10-07:00", "owner_resource": "customer", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893361341", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194711312} -{"stream": "metafield_customers", "data": {"id": 22346893394109, "namespace": "custom", "key": "test_definition", "value": "Taster", "description": null, "owner_id": 6569096478909, "created_at": "2023-04-13T04:50:10-07:00", "updated_at": "2023-04-13T04:50:10-07:00", "owner_resource": "customer", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893394109", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194711313} -{"stream": "metafield_draft_orders", "data": {"id": 22532787175613, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 929019691197, "created_at": "2023-04-24T07:18:06-07:00", "updated_at": "2023-04-24T07:18:06-07:00", "owner_resource": "draft_order", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22532787175613", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194714876} -{"stream":"metafield_locations","data":{"id":21524407255229,"namespace":"inventory","key":"warehouse_2","value":"234","description":null,"owner_id":63590301885,"created_at":"2022-10-12T02:21:27-07:00","updated_at":"2022-10-12T02:21:27-07:00","owner_resource":"location","type":"number_integer","admin_graphql_api_id":"gid://shopify/Metafield/21524407255229","shop_url":"airbyte-integration-test"},"emitted_at":1704314554082} -{"stream":"metafield_locations","data":{"id":21524407681213,"namespace":"inventory","key":"warehouse_233","value":"564","description":null,"owner_id":63590301885,"created_at":"2022-10-12T02:21:35-07:00","updated_at":"2022-10-12T02:21:35-07:00","owner_resource":"location","type":"number_integer","admin_graphql_api_id":"gid://shopify/Metafield/21524407681213","shop_url":"airbyte-integration-test"},"emitted_at":1704314554084} -{"stream": "metafield_orders", "data": {"id": 22347287855293, "namespace": "my_fields", "key": "purchase_order", "value": "trtrtr", "description": null, "owner_id": 4147980107965, "created_at": "2023-04-13T05:09:08-07:00", "updated_at": "2023-04-13T05:09:08-07:00", "owner_resource": "order", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347287855293", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194720313} -{"stream": "metafield_orders", "data": {"id": 22365749805245, "namespace": "my_fields", "key": "purchase_order", "value": "Test Draft Order Metafield", "description": null, "owner_id": 3935377129661, "created_at": "2023-04-14T03:52:40-07:00", "updated_at": "2023-04-14T03:52:40-07:00", "owner_resource": "order", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365749805245", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194720780} -{"stream": "metafield_pages", "data": {"id": 22534014828733, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 83074252989, "created_at": "2023-04-24T11:08:41-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "owner_resource": "page", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534014828733", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194723743} -{"stream": "metafield_product_images", "data": {"id": 22533588451517, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 29301297316029, "created_at": "2023-04-24T10:32:19-07:00", "updated_at": "2023-04-24T10:32:19-07:00", "owner_resource": "product_image", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22533588451517", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194726839} -{"stream": "metafield_products", "data": {"id": 22365706944701, "namespace": "custom", "key": "test_product_metafield", "value": "gid://shopify/Product/6796220989629", "description": null, "owner_id": 6796220989629, "created_at": "2023-04-14T03:15:07-07:00", "updated_at": "2023-04-14T03:15:07-07:00", "owner_resource": "product", "type": "product_reference", "admin_graphql_api_id": "gid://shopify/Metafield/22365706944701", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194728238} -{"stream": "metafield_products", "data": {"id": 22365762486461, "namespace": "custom", "key": "product_metafield_test_2", "value": "Test", "description": null, "owner_id": 6796220989629, "created_at": "2023-04-14T03:59:44-07:00", "updated_at": "2023-04-14T03:59:44-07:00", "owner_resource": "product", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365762486461", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194728239} -{"stream": "metafield_product_variants", "data": {"id": 22365715955901, "namespace": "custom", "key": "test_variant_metafield", "value": "Test Varia", "description": null, "owner_id": 41561961824445, "created_at": "2023-04-14T03:24:03-07:00", "updated_at": "2023-04-14T03:24:03-07:00", "owner_resource": "variant", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365715955901", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194733126} -{"stream": "metafield_shops", "data": {"id": 22534020104381, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 58033176765, "created_at": "2023-04-24T11:12:38-07:00", "updated_at": "2023-04-24T11:12:38-07:00", "owner_resource": "shop", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534020104381", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194734113} -{"stream": "metafield_smart_collections", "data": {"id": 21525604106429, "namespace": "my_fields", "key": "discount", "value": "50%", "description": null, "owner_id": 273278566589, "created_at": "2022-10-12T13:36:55-07:00", "updated_at": "2022-10-12T13:36:55-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21525604106429", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194736384} -{"stream": "metafield_smart_collections", "data": {"id": 22366265573565, "namespace": "my_fields", "key": "new_key", "value": "51%", "description": null, "owner_id": 273278566589, "created_at": "2023-04-14T05:21:58-07:00", "updated_at": "2023-04-14T05:21:58-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366265573565", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194736385} -{"stream": "order_refunds", "data": {"id": 829538369725, "order_id": 3935377129661, "created_at": "2021-09-21T05:31:59-07:00", "note": "test refund", "user_id": 74861019325, "processed_at": "2021-09-21T05:31:59-07:00", "restock": true, "duties": "[]", "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "return": null, "admin_graphql_api_id": "gid://shopify/Refund/829538369725", "refund_line_items": [{"id": 332807864509, "quantity": 1, "line_item_id": 10130216452285, "location_id": 63590301885, "restock_type": "cancel", "subtotal": 102.0, "total_tax": 17.0, "subtotal_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "line_item": {"id": 10130216452285, "variant_id": 40090604011709, "title": "8 Ounce Soy Candle", "quantity": 1, "sku": "", "variant_title": "Wooden", "vendor": "Bosco Inc", "fulfillment_service": "manual", "product_id": 6796229509309, "requires_shipping": true, "taxable": true, "gift_card": false, "name": "8 Ounce Soy Candle - Wooden", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 63, "price": 102.0, "total_discount": 0.0, "fulfillment_status": null, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "discount_allocations": [], "duties": [], "admin_graphql_api_id": "gid://shopify/LineItem/10130216452285", "tax_lines": [{"title": "PDV", "price": 17.0, "rate": 0.2, "channel_liable": false, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}}]}}], "transactions": [{"id": 5189894406333, "order_id": 3935377129661, "kind": "refund", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2021-09-21T05:31:58-07:00", "test": true, "authorization": null, "location_id": null, "user_id": 74861019325, "parent_id": 4933790040253, "processed_at": "2021-09-21T05:31:58-07:00", "device_id": null, "error_code": null, "source_name": "1830279", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 11, "credit_card_expiration_year": 2023}, "receipt": {"paid_amount": "102.00"}, "amount": "102.00", "currency": "USD", "payment_id": "c21670281707709.2", "total_unsettled_set": {"presentment_money": {"amount": "0.0", "currency": "USD"}, "shop_money": {"amount": "0.0", "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5189894406333"}], "order_adjustments": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194739764} -{"stream": "order_refunds", "data": {"id": 845032358077, "order_id": 4147980107965, "created_at": "2022-03-07T02:09:04-08:00", "note": null, "user_id": 74861019325, "processed_at": "2022-03-07T02:09:04-08:00", "restock": true, "duties": "[]", "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "return": {"id": 822313149, "admin_graphql_api_id": "gid://shopify/Return/822313149"}, "admin_graphql_api_id": "gid://shopify/Refund/845032358077", "refund_line_items": [{"id": 352716947645, "quantity": 1, "line_item_id": 10576771317949, "location_id": 63590301885, "restock_type": "return", "subtotal": 27.0, "total_tax": 0.0, "subtotal_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 10576771317949, "variant_id": 40090580615357, "title": "Red & Silver Fishing Lure", "quantity": 1, "sku": "", "variant_title": "Plastic", "vendor": "Harris - Hamill", "fulfillment_service": "manual", "product_id": 6796218302653, "requires_shipping": true, "taxable": true, "gift_card": false, "name": "Red & Silver Fishing Lure - Plastic", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 285, "price": 27.0, "total_discount": 0.0, "fulfillment_status": "fulfilled", "price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "discount_allocations": [], "duties": [], "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "tax_lines": []}}], "transactions": [], "order_adjustments": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194740336} -{"stream": "order_refunds", "data": {"id": 852809646269, "order_id": 4554821468349, "created_at": "2022-06-15T06:25:43-07:00", "note": null, "user_id": 74861019325, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "duties": "[]", "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "return": {"id": 947388605, "admin_graphql_api_id": "gid://shopify/Return/947388605"}, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "refund_line_items": [{"id": 363131404477, "quantity": 1, "line_item_id": 11406125564093, "location_id": 63590301885, "restock_type": "return", "subtotal": 57.23, "total_tax": 0.0, "subtotal_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "variant_id": 40090597884093, "title": "All Black Sneaker Right Foot", "quantity": 1, "sku": "", "variant_title": "ivory", "vendor": "Becker - Moore", "fulfillment_service": "manual", "product_id": 6796226560189, "requires_shipping": false, "taxable": true, "gift_card": false, "name": "All Black Sneaker Right Foot - ivory", "variant_inventory_management": "shopify", "properties": [], "product_exists": true, "fulfillable_quantity": 0, "grams": 0, "price": 59.0, "total_discount": 0.0, "fulfillment_status": "fulfilled", "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "discount_allocations": [{"amount": 1.77, "discount_application_index": 0, "amount_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}}], "duties": [], "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "tax_lines": []}}], "transactions": [{"id": 5721170968765, "order_id": 4554821468349, "kind": "refund", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2022-06-15T06:25:42-07:00", "test": true, "authorization": null, "location_id": null, "user_id": null, "parent_id": 5721110872253, "processed_at": "2022-06-15T06:25:42-07:00", "device_id": null, "error_code": null, "source_name": "1830279", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}, "receipt": {"paid_amount": "57.23"}, "amount": "57.23", "currency": "USD", "payment_id": "c25048437719229.2", "total_unsettled_set": {"presentment_money": {"amount": "0.0", "currency": "USD"}, "shop_money": {"amount": "0.0", "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765"}], "order_adjustments": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194740934} -{"stream": "order_risks", "data": {"id": 6446736474301, "order_id": 4147980107965, "checkout_id": null, "source": "External", "score": 1.0, "recommendation": "cancel", "display": true, "cause_cancel": true, "message": "This order came from an anonymous proxy", "merchant_message": "This order came from an anonymous proxy", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194743896} -{"stream": "orders", "data": {"id": 4554821468349, "admin_graphql_api_id": "gid://shopify/Order/4554821468349", "app_id": 580111, "browser_ip": "176.113.167.23", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 25048437719229, "checkout_token": "cf5d16a0a0688905bd551c6dec591506", "client_details": {"accept_language": "en-US,en;q=0.9,uk;q=0.8", "browser_height": 754, "browser_ip": "176.113.167.23", "browser_width": 1519, "session_hash": null, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53"}, "closed_at": "2022-06-15T06:25:43-07:00", "company": null, "confirmation_number": null, "confirmed": true, "contact_email": "integration-test@airbyte.io", "created_at": "2022-06-15T05:16:53-07:00", "currency": "USD", "current_subtotal_price": 0.0, "current_subtotal_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 0.0, "current_total_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_tax": 0.0, "current_total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "integration-test@airbyte.io", "estimated_taxes": false, "financial_status": "refunded", "fulfillment_status": "fulfilled", "landing_site": "/wallets/checkouts.json", "landing_site_ref": null, "location_id": null, "merchant_of_record_app_id": null, "name": "#1136", "note": "updated_mon_24.04.2023", "note_attributes": [], "number": 136, "order_number": 1136, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/e4f98630ea44a884e33e700203ce2130/authenticate?key=edf087d6ae55a4541bf1375432f6a4b8", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["bogus"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2022-06-15T05:16:53-07:00", "reference": null, "referring_site": "https://airbyte-integration-test.myshopify.com/products/all-black-sneaker-right-foot", "source_identifier": null, "source_name": "web", "source_url": null, "subtotal_price": 57.23, "subtotal_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "tags": "Refund", "tax_exempt": false, "tax_lines": [], "taxes_included": true, "test": true, "token": "e4f98630ea44a884e33e700203ce2130", "total_discounts": 1.77, "total_discounts_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}, "total_line_items_price": 59.0, "total_line_items_price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 57.23, "total_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 0, "updated_at": "2023-04-24T07:00:37-07:00", "user_id": null, "billing_address": {"first_name": "Iryna", "address1": "2261 Market Street", "phone": null, "city": "San Francisco", "zip": "94114", "province": "California", "country": "United States", "last_name": "Grankova", "address2": "4381", "company": null, "latitude": 37.7647751, "longitude": -122.4320369, "name": "Iryna Grankova", "country_code": "US", "province_code": "CA"}, "customer": {"id": 5362027233469, "email": "integration-test@airbyte.io", "accepts_marketing": false, "created_at": "2021-07-08T05:41:47-07:00", "updated_at": "2022-06-22T03:50:13-07:00", "first_name": "Airbyte", "last_name": "Team", "state": "disabled", "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "phone": null, "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "tags": "", "currency": "USD", "accepts_marketing_updated_at": "2021-07-08T05:41:47-07:00", "marketing_opt_in_level": null, "tax_exemptions": [], "admin_graphql_api_id": "gid://shopify/Customer/5362027233469", "default_address": {"id": 7492260823229, "customer_id": 5362027233469, "first_name": "Airbyte", "last_name": "Team", "company": null, "address1": "2261 Market Street", "address2": "4381", "city": "San Francisco", "province": "California", "country": "United States", "zip": "94114", "phone": null, "name": "Airbyte Team", "province_code": "CA", "country_code": "US", "country_name": "United States", "default": true}}, "discount_applications": [{"target_type": "line_item", "type": "automatic", "value": "3.0", "value_type": "percentage", "allocation_method": "across", "target_selection": "all", "title": "eeeee"}], "fulfillments": [{"id": 4075788501181, "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "created_at": "2022-06-15T05:16:55-07:00", "location_id": 63590301885, "name": "#1136.1", "order_id": 4554821468349, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2022-06-15T05:16:55-07:00", "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}]}], "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}], "payment_terms": null, "refunds": [{"id": 852809646269, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "created_at": "2022-06-15T06:25:43-07:00", "note": null, "order_id": 4554821468349, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5721170968765, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "amount": "57.23", "authorization": null, "created_at": "2022-06-15T06:25:42-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 4554821468349, "parent_id": 5721110872253, "payment_id": "c25048437719229.2", "processed_at": "2022-06-15T06:25:42-07:00", "receipt": {"paid_amount": "57.23"}, "source_name": "1830279", "status": "success", "test": true, "user_id": null, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}}], "refund_line_items": [{"id": 363131404477, "line_item_id": 11406125564093, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 57.23, "subtotal_set": {"shop_money": {"amount": "57.23", "currency_code": "USD"}, "presentment_money": {"amount": "57.23", "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": "59.00", "price_set": {"shop_money": {"amount": "59.00", "currency_code": "USD"}, "presentment_money": {"amount": "59.00", "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}}], "duties": []}], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194746441} -{"stream": "orders", "data": {"id": 4147980107965, "admin_graphql_api_id": "gid://shopify/Order/4147980107965", "app_id": 5505221, "browser_ip": null, "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": null, "checkout_token": null, "client_details": null, "closed_at": null, "company": null, "confirmation_number": null, "confirmed": true, "contact_email": "airbyte@airbyte.com", "created_at": "2021-09-19T09:08:23-07:00", "currency": "USD", "current_subtotal_price": 0.0, "current_subtotal_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 0.0, "current_total_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_tax": 0.0, "current_total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "customer_locale": null, "device_id": null, "discount_codes": [], "email": "airbyte@airbyte.com", "estimated_taxes": false, "financial_status": "paid", "fulfillment_status": "fulfilled", "landing_site": null, "landing_site_ref": null, "location_id": null, "merchant_of_record_app_id": null, "name": "#1121", "note": "updated_mon_24.04.2023", "note_attributes": [], "number": 121, "order_number": 1121, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/6adf11e07ccb49b280ea4b9f53d64f12/authenticate?key=4cef2ff10ba4d18f31114df33933f81e", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": [], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2021-09-19T09:08:23-07:00", "reference": null, "referring_site": null, "source_identifier": null, "source_name": "5505221", "source_url": null, "subtotal_price": 27.0, "subtotal_price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "tags": "", "tax_exempt": false, "tax_lines": [], "taxes_included": false, "test": false, "token": "6adf11e07ccb49b280ea4b9f53d64f12", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 27.0, "total_line_items_price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 27.0, "total_price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 0, "updated_at": "2023-04-24T07:03:06-07:00", "user_id": null, "billing_address": null, "customer": {"id": 5565161144509, "email": "airbyte@airbyte.com", "accepts_marketing": false, "created_at": "2021-09-19T08:31:05-07:00", "updated_at": "2021-09-19T09:08:24-07:00", "first_name": null, "last_name": null, "state": "disabled", "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "phone": null, "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "tags": "", "currency": "USD", "accepts_marketing_updated_at": "2021-09-19T08:31:05-07:00", "marketing_opt_in_level": null, "tax_exemptions": [], "admin_graphql_api_id": "gid://shopify/Customer/5565161144509"}, "discount_applications": [], "fulfillments": [{"id": 3693416710333, "admin_graphql_api_id": "gid://shopify/Fulfillment/3693416710333", "created_at": "2021-09-19T09:08:23-07:00", "location_id": 63590301885, "name": "#1121.1", "order_id": 4147980107965, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": "Amazon Logistics US", "tracking_number": "123456", "tracking_numbers": ["123456"], "tracking_url": "https://track.amazon.com/tracking/123456", "tracking_urls": ["https://track.amazon.com/tracking/123456"], "updated_at": "2022-02-22T00:35:47-08:00", "line_items": [{"id": 10576771317949, "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 285, "name": "Red & Silver Fishing Lure - Plastic", "price": 27.0, "price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796218302653, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "Red & Silver Fishing Lure", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090580615357, "variant_inventory_management": "shopify", "variant_title": "Plastic", "vendor": "Harris - Hamill", "tax_lines": [], "duties": [], "discount_allocations": []}]}], "line_items": [{"id": 10576771317949, "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 285, "name": "Red & Silver Fishing Lure - Plastic", "price": 27.0, "price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796218302653, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "Red & Silver Fishing Lure", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090580615357, "variant_inventory_management": "shopify", "variant_title": "Plastic", "vendor": "Harris - Hamill", "tax_lines": [], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [{"id": 845032358077, "admin_graphql_api_id": "gid://shopify/Refund/845032358077", "created_at": "2022-03-07T02:09:04-08:00", "note": null, "order_id": 4147980107965, "processed_at": "2022-03-07T02:09:04-08:00", "restock": true, "total_duties_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [], "refund_line_items": [{"id": 352716947645, "line_item_id": 10576771317949, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 27.0, "subtotal_set": {"shop_money": {"amount": "27.00", "currency_code": "USD"}, "presentment_money": {"amount": "27.00", "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "line_item": {"id": 10576771317949, "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 285, "name": "Red & Silver Fishing Lure - Plastic", "price": "27.00", "price_set": {"shop_money": {"amount": "27.00", "currency_code": "USD"}, "presentment_money": {"amount": "27.00", "currency_code": "USD"}}, "product_exists": true, "product_id": 6796218302653, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "Red & Silver Fishing Lure", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "variant_id": 40090580615357, "variant_inventory_management": "shopify", "variant_title": "Plastic", "vendor": "Harris - Hamill", "tax_lines": [], "duties": [], "discount_allocations": []}}], "duties": []}], "shipping_address": {"first_name": "John", "address1": "San Francisco", "phone": "", "city": "San Francisco", "zip": "91326", "province": "California", "country": "United States", "last_name": "Doe", "address2": "10", "company": "Umbrella LLC", "latitude": 34.2894584, "longitude": -118.5622893, "name": "John Doe", "country_code": "US", "province_code": "CA"}, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194746446} -{"stream": "orders", "data": {"id": 3935377129661, "admin_graphql_api_id": "gid://shopify/Order/3935377129661", "app_id": 1354745, "browser_ip": "76.14.176.236", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 21670281707709, "checkout_token": "ea03756d615a5f9e752f3c085e8cf9bd", "client_details": {"accept_language": "en-US,en;q=0.9", "browser_height": null, "browser_ip": "76.14.176.236", "browser_width": null, "session_hash": null, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"}, "closed_at": null, "company": null, "confirmation_number": null, "confirmed": true, "contact_email": null, "created_at": "2021-07-02T00:51:50-07:00", "currency": "USD", "current_subtotal_price": 0.0, "current_subtotal_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 0.0, "current_total_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_tax": 0.0, "current_total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "customer_locale": null, "device_id": null, "discount_codes": [], "email": "", "estimated_taxes": false, "financial_status": "refunded", "fulfillment_status": null, "landing_site": null, "landing_site_ref": null, "location_id": 63590301885, "merchant_of_record_app_id": null, "name": "#1001", "note": null, "note_attributes": [], "number": 1, "order_number": 1001, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/16dd6c6e17f562f1f5eee0fefa00b4cb/authenticate?key=931eb302588779d0ab93839d42bf7166", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["bogus"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2021-07-02T00:51:49-07:00", "reference": null, "referring_site": null, "source_identifier": null, "source_name": "shopify_draft_order", "source_url": null, "subtotal_price": 102.0, "subtotal_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "tags": "teest", "tax_exempt": false, "tax_lines": [{"price": 17.0, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "channel_liable": false}], "taxes_included": true, "test": true, "token": "16dd6c6e17f562f1f5eee0fefa00b4cb", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 102.0, "total_line_items_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 102.0, "total_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 63, "updated_at": "2023-04-24T10:59:00-07:00", "user_id": 74861019325, "billing_address": null, "customer": {"id": 5349364105405, "email": null, "accepts_marketing": false, "created_at": "2021-07-02T00:51:46-07:00", "updated_at": "2021-07-02T00:51:46-07:00", "first_name": "Bogus", "last_name": "Gateway", "state": "disabled", "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "phone": null, "email_marketing_consent": null, "sms_marketing_consent": null, "tags": "", "currency": "USD", "accepts_marketing_updated_at": "2021-07-02T00:51:46-07:00", "marketing_opt_in_level": null, "tax_exemptions": [], "admin_graphql_api_id": "gid://shopify/Customer/5349364105405"}, "discount_applications": [], "fulfillments": [], "line_items": [{"id": 10130216452285, "admin_graphql_api_id": "gid://shopify/LineItem/10130216452285", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": null, "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [{"id": 829538369725, "admin_graphql_api_id": "gid://shopify/Refund/829538369725", "created_at": "2021-09-21T05:31:59-07:00", "note": "test refund", "order_id": 3935377129661, "processed_at": "2021-09-21T05:31:59-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5189894406333, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5189894406333", "amount": "102.00", "authorization": null, "created_at": "2021-09-21T05:31:58-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 3935377129661, "parent_id": 4933790040253, "payment_id": "c21670281707709.2", "processed_at": "2021-09-21T05:31:58-07:00", "receipt": {"paid_amount": "102.00"}, "source_name": "1830279", "status": "success", "test": true, "user_id": 74861019325, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 11, "credit_card_expiration_year": 2023}}], "refund_line_items": [{"id": 332807864509, "line_item_id": 10130216452285, "location_id": 63590301885, "quantity": 1, "restock_type": "cancel", "subtotal": 102.0, "subtotal_set": {"shop_money": {"amount": "102.00", "currency_code": "USD"}, "presentment_money": {"amount": "102.00", "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": "17.00", "currency_code": "USD"}, "presentment_money": {"amount": "17.00", "currency_code": "USD"}}, "line_item": {"id": 10130216452285, "admin_graphql_api_id": "gid://shopify/LineItem/10130216452285", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": null, "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": "102.00", "price_set": {"shop_money": {"amount": "102.00", "currency_code": "USD"}, "presentment_money": {"amount": "102.00", "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": "17.00", "price_set": {"shop_money": {"amount": "17.00", "currency_code": "USD"}, "presentment_money": {"amount": "17.00", "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}}], "duties": []}], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194746449} -{"stream": "pages", "data": {"id": 83074252989, "title": "Warranty information", "shop_id": 58033176765, "handle": "warranty-information", "body_html": "updated_mon_24.04.2023", "author": "Shopify API", "created_at": "2021-07-08T05:19:00-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "published_at": "2021-07-08T05:19:00-07:00", "template_suffix": null, "admin_graphql_api_id": "gid://shopify/OnlineStorePage/83074252989", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194747936} -{"stream": "pages", "data": {"id": 95926616253, "deleted_at": "2023-09-06T03:37:06-07:00", "updated_at": "2023-09-06T03:37:06-07:00", "deleted_message": "Online Store deleted a page: Test Page for delete.", "deleted_description": "Online Store deleted a page: Test Page for delete.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194748486} -{"stream": "price_rules", "data": {"id": 945000284349, "value_type": "percentage", "value": "-3.0", "customer_selection": "all", "target_type": "line_item", "target_selection": "all", "allocation_method": "across", "allocation_limit": null, "once_per_customer": true, "usage_limit": 10, "starts_at": "2021-07-07T07:22:04-07:00", "ends_at": null, "created_at": "2021-07-07T07:23:11-07:00", "updated_at": "2023-04-24T05:52:22-07:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": null, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "1V8Z165KSH5T", "admin_graphql_api_id": "gid://shopify/PriceRule/945000284349", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194749554} -{"stream": "price_rules", "data": {"id": 1278552473789, "deleted_at": "2023-09-06T03:48:46-07:00", "updated_at": "2023-09-06T03:48:46-07:00", "deleted_message": "Airbyte Test deleted this discount.", "deleted_description": "Airbyte Test deleted this discount.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194750128} -{"stream": "product_images", "data": {"id": 29301297316029, "product_id": 6796220989629, "position": 1, "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2023-04-24T10:32:19-07:00", "alt": "updated_mon_24.04.2023", "width": 2200, "height": 1467, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/4-ounce-soy-candle.jpg?v=1682357539", "variant_ids": [], "admin_graphql_api_id": "gid://shopify/ProductImage/29301297316029", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194752617} -{"stream": "products", "data": {"id": 6796220989629, "title": "4 Ounce Soy Candle", "body_html": "updated_mon_24.04.2023", "vendor": "Hartmann Group", "product_type": "Baby", "created_at": "2021-06-22T18:09:47-07:00", "handle": "4-ounce-soy-candle", "updated_at": "2023-04-24T11:05:13-07:00", "published_at": "2021-06-22T18:09:47-07:00", "template_suffix": "", "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796220989629", "variants": [{"id": 40090585923773, "product_id": 6796220989629, "title": "Metal", "price": 19.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Metal", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2023-04-13T05:00:55-07:00", "taxable": true, "barcode": null, "grams": 112, "image_id": null, "weight": 112.0, "weight_unit": "g", "inventory_item_id": 42185200631997, "inventory_quantity": 15, "old_inventory_quantity": 15, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090585923773"}, {"id": 41561955827901, "product_id": 6796220989629, "title": "Test Variant 1", "price": 19.0, "sku": "", "position": 2, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Test Variant 1", "option2": null, "option3": null, "created_at": "2022-03-06T14:09:20-08:00", "updated_at": "2022-03-06T14:12:40-08:00", "taxable": true, "barcode": "", "grams": 112, "image_id": null, "weight": 112.0, "weight_unit": "g", "inventory_item_id": 43653682495677, "inventory_quantity": 2, "old_inventory_quantity": 2, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/41561955827901"}, {"id": 41561961824445, "product_id": 6796220989629, "title": "Test Variant 2", "price": 19.0, "sku": "", "position": 3, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Test Variant 2", "option2": null, "option3": null, "created_at": "2022-03-06T14:12:20-08:00", "updated_at": "2023-04-24T11:00:10-07:00", "taxable": true, "barcode": "", "grams": 112, "image_id": null, "weight": 112.0, "weight_unit": "g", "inventory_item_id": 43653688524989, "inventory_quantity": 0, "old_inventory_quantity": 0, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/41561961824445"}], "options": [{"id": 8720178315453, "product_id": 6796220989629, "name": "Title", "position": 1, "values": ["Metal", "Test Variant 1", "Test Variant 2"]}], "images": [{"id": 29301297316029, "product_id": 6796220989629, "position": 1, "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2023-04-24T10:32:19-07:00", "alt": "updated_mon_24.04.2023", "width": 2200, "height": 1467, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/4-ounce-soy-candle.jpg?v=1682357539", "variant_ids": [], "admin_graphql_api_id": "gid://shopify/ProductImage/29301297316029"}], "image": {"id": 29301297316029, "product_id": 6796220989629, "position": 1, "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2023-04-24T10:32:19-07:00", "alt": "updated_mon_24.04.2023", "width": 2200, "height": 1467, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/4-ounce-soy-candle.jpg?v=1682357539", "variant_ids": [], "admin_graphql_api_id": "gid://shopify/ProductImage/29301297316029"}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194753037} -{"stream": "products", "data": {"id": 6796217843901, "title": "Lace Detail On Womens Top", "body_html": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "vendor": "Hayes, Hettinger and Hauck", "product_type": "Beauty", "created_at": "2021-06-22T18:09:26-07:00", "handle": "lace-detail-on-womens-top", "updated_at": "2023-09-05T07:12:05-07:00", "published_at": null, "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "archived", "admin_graphql_api_id": "gid://shopify/Product/6796217843901", "variants": [{"id": 40090579959997, "product_id": 6796217843901, "title": "Soft", "price": 85.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Soft", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2021-06-22T18:09:27-07:00", "taxable": true, "barcode": null, "grams": 391, "image_id": null, "weight": 391.0, "weight_unit": "g", "inventory_item_id": 42185194668221, "inventory_quantity": 12, "old_inventory_quantity": 12, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579959997"}], "options": [{"id": 8720175169725, "product_id": 6796217843901, "name": "Title", "position": 1, "values": ["Soft"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194753040} -{"stream": "products", "data": {"id": 6796217811133, "deleted_at": "2023-09-05T07:07:00-07:00", "updated_at": "2023-09-05T07:07:00-07:00", "deleted_message": "Airbyte Airbyte deleted a product: Yoga Mat Rolled.", "deleted_description": "Airbyte Airbyte deleted a product: Yoga Mat Rolled.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194753917} -{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217843901", "title": "Lace Detail On Womens Top", "updatedAt": "2023-09-05T14:12:05Z", "createdAt": "2021-06-23T01:09:26Z", "publishedAt": null, "status": "ARCHIVED", "vendor": "Hayes, Hettinger and Hauck", "productType": "Beauty", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175169725", "name": "Title", "position": 1, "values": ["Soft"]}], "handle": "lace-detail-on-womens-top", "description": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "tracksInventory": true, "totalInventory": 12, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://xozdpweqwavev7lh-58033176765.shopifypreview.com/products_preview?preview_key=6fd9afd8977385d048b67ffb24ad7a7f&_bt=eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaXRoYVhKaWVYUmxMV2x1ZEdWbmNtRjBhVzl1TFhSbGMzUXViWGx6YUc5d2FXWjVMbU52YlFZNkJrVlUiLCJleHAiOiIyMDIzLTEwLTEzVDExOjU5OjE0LjkwNFoiLCJwdXIiOiJwZXJtYW5lbnRfcGFzc3dvcmRfYnlwYXNzIn19--aee5ded34bedee80bb841b77b1205d58a10f607e", "descriptionHtml": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "isGiftCard": false, "legacyResourceId": "6796217843901", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194755072} -{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796220989629", "title": "4 Ounce Soy Candle", "updatedAt": "2023-04-24T18:05:13Z", "createdAt": "2021-06-23T01:09:47Z", "publishedAt": "2021-06-23T01:09:47Z", "status": "ACTIVE", "vendor": "Hartmann Group", "productType": "Baby", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720178315453", "name": "Title", "position": 1, "values": ["Metal", "Test Variant 1", "Test Variant 2"]}], "handle": "4-ounce-soy-candle", "description": "updated_mon_24.04.2023", "tracksInventory": true, "totalInventory": 17, "totalVariants": 3, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://airbyte-integration-test.myshopify.com/products/4-ounce-soy-candle", "descriptionHtml": "updated_mon_24.04.2023", "isGiftCard": false, "legacyResourceId": "6796220989629", "mediaCount": 1, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194755073} -{"stream": "product_variants", "data": {"id": 40090579959997, "product_id": 6796217843901, "title": "Soft", "price": 85.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Soft", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2021-06-22T18:09:27-07:00", "taxable": true, "barcode": null, "grams": 391, "image_id": null, "weight": 391.0, "weight_unit": "g", "inventory_item_id": 42185194668221, "inventory_quantity": 12, "old_inventory_quantity": 12, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579959997", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194757681} -{"stream": "product_variants", "data": {"id": 40090585923773, "product_id": 6796220989629, "title": "Metal", "price": 19.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Metal", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:47-07:00", "updated_at": "2023-04-13T05:00:55-07:00", "taxable": true, "barcode": null, "grams": 112, "image_id": null, "weight": 112.0, "weight_unit": "g", "inventory_item_id": 42185200631997, "inventory_quantity": 15, "old_inventory_quantity": 15, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090585923773", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194758143} -{"stream": "product_variants", "data": {"id": 41561955827901, "product_id": 6796220989629, "title": "Test Variant 1", "price": 19.0, "sku": "", "position": 2, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Test Variant 1", "option2": null, "option3": null, "created_at": "2022-03-06T14:09:20-08:00", "updated_at": "2022-03-06T14:12:40-08:00", "taxable": true, "barcode": "", "grams": 112, "image_id": null, "weight": 112.0, "weight_unit": "g", "inventory_item_id": 43653682495677, "inventory_quantity": 2, "old_inventory_quantity": 2, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/41561955827901", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194758144} -{"stream": "shop", "data": {"id": 58033176765, "name": "airbyte integration test", "email": "sherif@airbyte.io", "domain": "airbyte-integration-test.myshopify.com", "province": "California", "country": "US", "address1": "350 29th Avenue", "zip": "94121", "city": "San Francisco", "source": null, "phone": "8023494963", "latitude": 37.7827286, "longitude": -122.4889911, "primary_locale": "en", "address2": "", "created_at": "2021-06-22T18:00:23-07:00", "updated_at": "2023-04-30T09:02:52-07:00", "country_code": "US", "country_name": "United States", "currency": "USD", "customer_email": "sherif@airbyte.io", "timezone": "(GMT-08:00) America/Los_Angeles", "iana_timezone": "America/Los_Angeles", "shop_owner": "Airbyte Airbyte", "money_format": "${{amount}}", "money_with_currency_format": "${{amount}} USD", "weight_unit": "kg", "province_code": "CA", "taxes_included": true, "auto_configure_tax_inclusivity": null, "tax_shipping": null, "county_taxes": true, "plan_display_name": "Developer Preview", "plan_name": "partner_test", "has_discounts": true, "has_gift_cards": false, "myshopify_domain": "airbyte-integration-test.myshopify.com", "google_apps_domain": null, "google_apps_login_enabled": null, "money_in_emails_format": "${{amount}}", "money_with_currency_in_emails_format": "${{amount}} USD", "eligible_for_payments": true, "requires_extra_payments_agreement": false, "password_enabled": true, "has_storefront": true, "finances": true, "primary_location_id": 63590301885, "checkout_api_supported": true, "multi_location_enabled": true, "setup_required": false, "pre_launch_enabled": false, "enabled_presentment_currencies": ["USD"], "transactional_sms_disabled": false, "marketing_sms_consent_enabled_at_checkout": false, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194759349} -{"stream": "smart_collections", "data": {"id": 273278566589, "handle": "test-collection", "title": "Test Collection", "updated_at": "2023-09-05T07:12:04-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-07-19T07:02:54-07:00", "sort_order": "best-selling", "template_suffix": "", "disjunctive": false, "rules": ["{'column': 'type', 'relation': 'equals', 'condition': 'Beauty'}"], "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/273278566589", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194760379} -{"stream": "tender_transactions", "data": {"id": 4464009117885, "order_id": 5033391718589, "amount": "19.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-24T11:00:08-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194761405} -{"stream": "transactions", "data": {"id": 5721110872253, "order_id": 4554821468349, "kind": "sale", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2022-06-15T05:16:52-07:00", "test": true, "authorization": "53433", "location_id": null, "user_id": null, "parent_id": null, "processed_at": "2022-06-15T05:16:52-07:00", "device_id": null, "error_code": null, "source_name": "580111", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}, "receipt": {"paid_amount": "57.23"}, "amount": 57.23, "currency": "USD", "payment_id": "c25048437719229.1", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721110872253", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194763489} -{"stream": "transactions", "data": {"id": 5721170968765, "order_id": 4554821468349, "kind": "refund", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2022-06-15T06:25:42-07:00", "test": true, "authorization": null, "location_id": null, "user_id": null, "parent_id": 5721110872253, "processed_at": "2022-06-15T06:25:42-07:00", "device_id": null, "error_code": null, "source_name": "1830279", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}, "receipt": {"paid_amount": "57.23"}, "amount": 57.23, "currency": "USD", "payment_id": "c25048437719229.2", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194763490} -{"stream": "transactions", "data": {"id": 4933790040253, "order_id": 3935377129661, "kind": "sale", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2021-07-02T00:51:49-07:00", "test": true, "authorization": "53433", "location_id": null, "user_id": null, "parent_id": null, "processed_at": "2021-07-02T00:51:49-07:00", "device_id": null, "error_code": null, "source_name": "shopify_draft_order", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 11, "credit_card_expiration_year": 2023}, "receipt": {"paid_amount": "102.00"}, "amount": 102.0, "currency": "USD", "payment_id": "c21670281707709.1", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/4933790040253", "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194764447} -{"stream": "customer_address", "data": {"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194770214} -{"stream": "customer_address", "data": {"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true, "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194770676} -{"stream": "countries", "data": {"id": 417014841533, "name": "Rest of World", "code": "*", "tax_name": "Tax", "tax": 0.0, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194771844} -{"stream": "countries", "data": {"id": 417014808765, "name": "Ukraine", "code": "UA", "tax_name": "PDV", "tax": 0.2, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1697194771845} +{"stream": "articles", "data": {"id": 558137508029, "title": "My new Article title", "created_at": "2022-10-07T16:09:02-07:00", "body_html": "

I like articles

\n

Yea, I like posting them through REST.

", "blog_id": 80417685693, "author": "John Smith", "user_id": null, "published_at": "2011-03-24T08:45:47-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "summary_html": null, "template_suffix": null, "handle": "my-new-article-title", "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558137508029", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953761718} +{"stream": "articles", "data": {"id": 558627979453, "title": "Test Blog Post", "created_at": "2023-04-14T03:19:02-07:00", "body_html": "Test Blog Post 1", "blog_id": 80417685693, "author": "Airbyte Airbyte", "user_id": "74861019325", "published_at": null, "updated_at": "2023-04-14T03:19:18-07:00", "summary_html": "", "template_suffix": "", "handle": "test-blog-post", "tags": "Has Been Tagged", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558627979453", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953761720} +{"stream": "articles", "data": {"id": 558999371965, "deleted_at": "2023-09-05T13:50:04-07:00", "updated_at": "2023-09-05T13:50:04-07:00", "deleted_message": "Online Store deleted an article: Test Article 1.", "deleted_description": "Online Store deleted an article: Test Article 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953762282} +{"stream": "blogs", "data": {"id": 80417685693, "handle": "news", "title": "News", "updated_at": "2023-09-05T14:02:00-07:00", "commentable": "no", "feedburner": null, "feedburner_location": null, "created_at": "2021-06-22T18:00:25-07:00", "template_suffix": null, "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreBlog/80417685693", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953764270} +{"stream": "blogs", "data": {"id": 85733114045, "deleted_at": "2023-09-06T03:30:22-07:00", "updated_at": "2023-09-06T03:30:22-07:00", "deleted_message": "Online Store deleted a blog: Test Blog 1.", "deleted_description": "Online Store deleted a blog: Test Blog 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953764809} +{"stream": "collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T14:06:59+00:00", "body_html": "updated_mon_24.04.2023", "sort_order": "BEST_SELLING", "template_suffix": "", "products_count": 1, "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "published_at": "2021-06-23T01:00:25+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953771931} +{"stream": "collections", "data": {"id": 273278566589, "handle": "test-collection", "title": "Test Collection", "updated_at": "2023-09-05T14:12:04+00:00", "body_html": "updated_mon_24.04.2023", "sort_order": "BEST_SELLING", "template_suffix": "", "products_count": 26, "admin_graphql_api_id": "gid://shopify/Collection/273278566589", "published_at": "2021-07-19T14:02:54+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953771932} +{"stream": "collects", "data": {"id": 29427031703741, "collection_id": 270889287869, "product_id": 6796220989629, "created_at": "2021-07-19T07:01:36-07:00", "updated_at": "2022-03-06T14:12:21-08:00", "position": 2, "sort_value": "0000000002", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953772898} +{"stream": "custom_collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T07:06:59-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-06-22T18:00:25-07:00", "sort_order": "best-selling", "template_suffix": "", "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953773873} +{"stream": "custom_collections", "data": {"id": 294253822141, "deleted_at": "2023-09-06T03:34:39-07:00", "updated_at": "2023-09-06T03:34:39-07:00", "deleted_message": "Airbyte Airbyte deleted a collection.", "deleted_description": "Airbyte Airbyte deleted a collection.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953774396} +{"stream": "customers", "data": {"id": 6569096478909, "email": "test@test.com", "created_at": "2023-04-13T02:30:04-07:00", "updated_at": "2023-04-24T06:53:48-07:00", "first_name": "New Test", "last_name": "Customer", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": "updated_mon_24.04.2023", "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": "+380639379992", "addresses": [{"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}], "accepts_marketing": true, "accepts_marketing_updated_at": "2023-04-13T02:30:04-07:00", "marketing_opt_in_level": "single_opt_in", "tax_exemptions": "[]", "email_marketing_consent": {"state": "subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": "2023-04-13T02:30:04-07:00"}, "sms_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null, "consent_collected_from": "SHOPIFY"}, "admin_graphql_api_id": "gid://shopify/Customer/6569096478909", "default_address": {"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953775493} +{"stream": "customers", "data": {"id": 6676027932861, "email": "marcos@airbyte.io", "created_at": "2023-07-11T13:07:45-07:00", "updated_at": "2023-07-11T13:07:45-07:00", "first_name": "MArcos", "last_name": "Millnitz", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": null, "addresses": [{"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}], "accepts_marketing": false, "accepts_marketing_updated_at": null, "marketing_opt_in_level": "single_opt_in", "tax_exemptions": "[]", "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "admin_graphql_api_id": "gid://shopify/Customer/6676027932861", "default_address": {"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953775495} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "updated_mon_24.04.2023", "id": 11539415990461, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/11539415990461", "price_rule_id": 945000284349, "updated_at": "2023-04-24T12:52:22+00:00", "created_at": "2021-07-07T14:23:11+00:00", "summary": "3% off entire order \u2022 One use per customer", "discount_type": "ORDER", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953782734} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "HZAVNV2487WC", "id": 11545139282109, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/11545139282109", "price_rule_id": 945205379261, "updated_at": "2023-12-07T11:40:44+00:00", "created_at": "2021-07-08T12:40:37+00:00", "summary": "Free shipping on all products \u2022 Minimum purchase of $1.00 \u2022 For all countries", "discount_type": "SHIPPING", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953782734} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "SUMMERSALE10OFF", "id": 13175793582269, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/13175793582269", "price_rule_id": 945205379261, "updated_at": "2023-12-07T11:40:44+00:00", "created_at": "2021-07-08T12:40:37+00:00", "summary": "Free shipping on all products \u2022 Minimum purchase of $1.00 \u2022 For all countries", "discount_type": "SHIPPING", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953782734} +{"stream": "draft_orders", "data": {"id": 874683629757, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2021-07-02T00:50:29-07:00", "updated_at": "2023-04-14T05:16:33-07:00", "tax_exempt": false, "completed_at": "2021-07-02T00:51:50-07:00", "name": "#D2", "status": "completed", "line_items": [{"id": 57443281666237, "variant_id": 40090604011709, "product_id": 6796229509309, "title": "8 Ounce Soy Candle", "variant_title": "Wooden", "sku": "", "vendor": "Bosco Inc", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 63, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 17.0}], "applied_discount": null, "name": "8 Ounce Soy Candle - Wooden", "properties": [], "custom": false, "price": 102.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/57443281666237"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/e155e3254d0c0d64fa90587de417e0f3", "applied_discount": null, "order_id": 3935377129661, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 17.0}], "tags": "", "note_attributes": [], "total_price": "102.00", "subtotal_price": "102.00", "total_tax": "17.00", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/874683629757", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953784884} +{"stream": "draft_orders", "data": {"id": 929019691197, "note": "updated_mon_24.04.2023", "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2022-02-22T03:23:19-08:00", "updated_at": "2023-04-24T07:18:06-07:00", "tax_exempt": false, "completed_at": null, "name": "#D21", "status": "open", "line_items": [{"id": 58117295538365, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 2, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295538365"}, {"id": 58117295571133, "variant_id": null, "product_id": null, "title": "Test Item", "variant_title": null, "sku": null, "vendor": null, "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 1000, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 0.17}], "applied_discount": null, "name": "Test Item", "properties": [], "custom": true, "price": 1.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295571133"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/12893992cc01fc67935ab014fcf9300f", "applied_discount": null, "order_id": null, "shipping_line": {"title": "Test Shipping Fee", "custom": true, "handle": null, "price": 3.0}, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}, {"rate": 0.2, "title": "PDV", "price": 0.17}], "tags": "", "note_attributes": [], "total_price": "42.00", "subtotal_price": "39.00", "total_tax": "6.50", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/929019691197", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953784892} +{"stream": "draft_orders", "data": {"id": 987391033533, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2023-04-13T04:56:17-07:00", "updated_at": "2023-04-13T04:56:17-07:00", "tax_exempt": false, "completed_at": null, "name": "#D25", "status": "open", "line_items": [{"id": 58116862083261, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.16}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862083261"}, {"id": 58116862116029, "variant_id": 41561955827901, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Test Variant 1", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Test Variant 1", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862116029"}, {"id": 58116862148797, "variant_id": 41561961824445, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Test Variant 2", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Test Variant 2", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862148797"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/d193a965f7815817a2d37fddb30bfdb2", "applied_discount": null, "order_id": null, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.16}, {"rate": 0.2, "title": "PDV", "price": 3.17}, {"rate": 0.2, "title": "PDV", "price": 3.17}], "tags": "", "note_attributes": [], "total_price": "57.00", "subtotal_price": "57.00", "total_tax": "9.50", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/987391033533", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953784893} +{"stream": "fulfillment_orders", "data": {"id": 5962451452093, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 431686549693, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-13T12:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-13T12:09:45+00:00", "updated_at": "2023-04-13T12:09:46+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5962451452093", "shop_id": 58033176765, "order_id": 5010584895677, "assigned_location_id": 63590301885, "line_items": [{"id": 12363725996221, "inventory_item_id": 42185218719933, "shop_id": 58033176765, "fulfillment_order_id": 5962451452093, "quantity": 1, "line_item_id": 12204214845629, "fulfillable_quantity": 0, "variant_id": 40090604011709}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953792126} +{"stream": "fulfillment_orders", "data": {"id": 5962452467901, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 431687532733, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-13T12:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-13T12:11:16+00:00", "updated_at": "2023-04-13T12:11:16+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5962452467901", "shop_id": 58033176765, "order_id": 5010585911485, "assigned_location_id": 63590301885, "line_items": [{"id": 12363727536317, "inventory_item_id": 43653688524989, "shop_id": 58033176765, "fulfillment_order_id": 5962452467901, "quantity": 1, "line_item_id": 12204216385725, "fulfillable_quantity": 0, "variant_id": 41561961824445}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953792129} +{"stream": "fulfillment_orders", "data": {"id": 5985636450493, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 442031046845, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-24T18:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-24T18:00:09+00:00", "updated_at": "2023-04-24T18:00:09+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5985636450493", "shop_id": 58033176765, "order_id": 5033391718589, "assigned_location_id": 63590301885, "line_items": [{"id": 12407122067645, "inventory_item_id": 43653688524989, "shop_id": 58033176765, "fulfillment_order_id": 5985636450493, "quantity": 1, "line_item_id": 12247585521853, "fulfillable_quantity": 0, "variant_id": 41561961824445}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953792131} +{"stream": "fulfillments", "data": {"id": 4451164913853, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451164913853", "created_at": "2023-04-13T05:09:45-07:00", "location_id": 63590301885, "name": "#1143.1", "order_id": 5010584895677, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:09:45-07:00", "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": "102.00", "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953793256} +{"stream": "fulfillments", "data": {"id": 4451169501373, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451169501373", "created_at": "2023-04-13T05:11:16-07:00", "location_id": 63590301885, "name": "#1144.1", "order_id": 5010585911485, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:11:16-07:00", "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": "19.00", "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953793263} +{"stream": "fulfillments", "data": {"id": 4075788501181, "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "created_at": "2022-06-15T05:16:55-07:00", "location_id": 63590301885, "name": "#1136.1", "order_id": 4554821468349, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2022-06-15T05:16:55-07:00", "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": "59.00", "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953793275} +{"stream": "inventory_items", "data": {"id": 44871665713341, "country_code_of_origin": null, "harmonized_system_code": null, "province_code_of_origin": null, "updated_at": "2023-04-14T10:29:27+00:00", "created_at": "2023-04-14T10:29:27+00:00", "sku": "", "tracked": true, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/InventoryItem/44871665713341", "cost": 60.0, "country_harmonized_system_codes": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953800805} +{"stream": "inventory_items", "data": {"id": 45419395743933, "country_code_of_origin": "UA", "harmonized_system_code": "330510", "province_code_of_origin": null, "updated_at": "2023-12-11T10:37:41+00:00", "created_at": "2023-12-11T10:37:41+00:00", "sku": "123", "tracked": true, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/InventoryItem/45419395743933", "cost": 29.0, "country_harmonized_system_codes": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953800806} +{"stream": "inventory_levels", "data": {"id": "63590301885|42185200631997", "available": 15, "updated_at": "2023-04-13T12:00:55+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185200631997", "inventory_item_id": 42185200631997, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953807899} +{"stream": "inventory_levels", "data": {"id": "63590301885|42185218719933", "available": 8, "updated_at": "2023-04-13T12:09:45+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185218719933", "inventory_item_id": 42185218719933, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953807904} +{"stream": "inventory_levels", "data": {"id": "63590301885|43653688524989", "available": 0, "updated_at": "2023-04-24T18:00:10+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=43653688524989", "inventory_item_id": 43653688524989, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953807905} +{"stream": "locations", "data": {"id": 63590301885, "name": "Heroiv UPA 72", "address1": "Heroiv UPA 72", "address2": "", "city": "Lviv", "zip": "30100", "province": null, "country": "UA", "phone": "", "created_at": "2021-06-22T18:00:29-07:00", "updated_at": "2023-11-28T07:08:27-08:00", "country_code": "UA", "country_name": "Ukraine", "province_code": null, "legacy": false, "active": true, "admin_graphql_api_id": "gid://shopify/Location/63590301885", "localized_country_name": "Ukraine", "localized_province_name": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953808895} +{"stream": "metafield_articles", "data": {"id": 21519818162365, "namespace": "global", "key": "new", "value": "newvalue", "description": null, "owner_id": 558137508029, "created_at": "2022-10-07T16:09:02-07:00", "updated_at": "2022-10-07T16:09:02-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519818162365", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953810882} +{"stream": "metafield_articles", "data": {"id": 22365709992125, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Article Metafield", "description": null, "owner_id": 558137508029, "created_at": "2023-04-14T03:18:26-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365709992125", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953810884} +{"stream": "metafield_articles", "data": {"id": 22365710352573, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Blog Post Metafiled", "description": null, "owner_id": 558627979453, "created_at": "2023-04-14T03:19:18-07:00", "updated_at": "2023-04-14T03:19:18-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710352573", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953811338} +{"stream": "metafield_blogs", "data": {"id": 21519428255933, "namespace": "some_fields", "key": "sponsor", "value": "Shopify", "description": null, "owner_id": 80417685693, "created_at": "2022-10-07T06:05:23-07:00", "updated_at": "2022-10-07T06:05:23-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519428255933", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953813888} +{"stream": "metafield_blogs", "data": {"id": 22365710745789, "namespace": "custom", "key": "test_blog_metafield", "value": "Test Blog Metafield", "description": null, "owner_id": 80417685693, "created_at": "2023-04-14T03:20:20-07:00", "updated_at": "2023-04-14T03:20:20-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710745789", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953813890} +{"stream": "metafield_collections", "data": {"id": 22365707174077, "namespace": "custom", "value": "Test Collection Metafield", "key": "test_collection_metafield", "description": null, "created_at": "2023-04-14T10:15:30+00:00", "updated_at": "2023-04-14T10:15:30+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365707174077", "owner_id": 270889287869, "owner_resource": "collection", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953821449} +{"stream": "metafield_collections", "data": {"id": 22366265573565, "namespace": "my_fields", "value": "51%", "key": "new_key", "description": null, "created_at": "2023-04-14T12:21:58+00:00", "updated_at": "2023-04-14T12:21:58+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366265573565", "owner_id": 273278566589, "owner_resource": "collection", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953821450} +{"stream": "metafield_customers", "data": {"id": 22346893361341, "namespace": "custom", "value": "Teste\n", "key": "test_definition_list_1", "description": null, "created_at": "2023-04-13T11:50:10+00:00", "updated_at": "2023-04-13T11:50:10+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893361341", "owner_id": 6569096478909, "owner_resource": "customer", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953828534} +{"stream": "metafield_customers", "data": {"id": 22346893394109, "namespace": "custom", "value": "Taster", "key": "test_definition", "description": null, "created_at": "2023-04-13T11:50:10+00:00", "updated_at": "2023-04-13T11:50:10+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893394109", "owner_id": 6569096478909, "owner_resource": "customer", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953828534} +{"stream": "metafield_draft_orders", "data": {"id": 22366258528445, "namespace": "discounts", "value": "50%", "key": "hello", "description": null, "created_at": "2023-04-14T12:16:33+00:00", "updated_at": "2023-04-14T12:16:33+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366258528445", "owner_id": 874683629757, "owner_resource": "draft_order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953835570} +{"stream": "metafield_draft_orders", "data": {"id": 22532787175613, "namespace": "new_metafield", "value": "updated_mon_24.04.2023", "key": "new_metafield", "description": null, "created_at": "2023-04-24T14:18:06+00:00", "updated_at": "2023-04-24T14:18:06+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22532787175613", "owner_id": 929019691197, "owner_resource": "draft_order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953835572} +{"stream": "metafield_locations", "data": {"id": 26246034161853, "namespace": "custom", "value": "2023-11-28 updated", "key": "test_location_metafield", "description": null, "created_at": "2023-11-28T15:08:26+00:00", "updated_at": "2023-11-28T15:08:26+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/26246034161853", "owner_id": 63590301885, "owner_resource": "location", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953842618} +{"stream": "metafield_orders", "data": {"id": 22347288150205, "namespace": "my_fields", "value": "asdfasdf", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:09:50+00:00", "updated_at": "2023-04-13T12:09:50+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347288150205", "owner_id": 5010584895677, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953849753} +{"stream": "metafield_orders", "data": {"id": 22347288740029, "namespace": "my_fields", "value": "asdfasdfasdf", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:11:20+00:00", "updated_at": "2023-04-13T12:11:20+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347288740029", "owner_id": 5010585911485, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953849753} +{"stream": "metafield_orders", "data": {"id": 22347287855293, "namespace": "my_fields", "value": "trtrtr", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:09:08+00:00", "updated_at": "2023-04-13T12:09:08+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347287855293", "owner_id": 4147980107965, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953849754} +{"stream": "metafield_pages", "data": {"id": 22365711499453, "namespace": "custom", "key": "test_page_metafield", "value": "Test Page Metafield", "description": null, "owner_id": 93795909821, "created_at": "2023-04-14T03:21:49-07:00", "updated_at": "2023-04-14T03:21:49-07:00", "owner_resource": "page", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365711499453", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953851755} +{"stream": "metafield_pages", "data": {"id": 22534014828733, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 83074252989, "created_at": "2023-04-24T11:08:41-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "owner_resource": "page", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534014828733", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953852192} +{"stream": "metafield_product_images", "data": {"id": 22365851517117, "namespace": "my_fields", "value": "natural coton", "key": "liner_material", "description": null, "created_at": "2023-04-14T11:59:27+00:00", "updated_at": "2023-04-14T11:59:27+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365851517117", "owner_id": 29301295481021, "owner_resource": "product_image", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953865505} +{"stream": "metafield_product_images", "data": {"id": 22533588451517, "namespace": "new_metafield", "value": "updated_mon_24.04.2023", "key": "new_metafield", "description": null, "created_at": "2023-04-24T17:32:19+00:00", "updated_at": "2023-04-24T17:32:19+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22533588451517", "owner_id": 29301297316029, "owner_resource": "product_image", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953865509} +{"stream": "metafield_products", "data": {"id": 22365729718461, "namespace": "custom", "value": "Test Product Metafield", "key": "product_metafield_test_2", "description": null, "created_at": "2023-04-14T10:31:19+00:00", "updated_at": "2023-04-14T10:31:19+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365729718461", "owner_id": 6796226560189, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953872773} +{"stream": "metafield_products", "data": {"id": 22365729816765, "namespace": "custom", "value": "gid://shopify/Product/6796229574845", "key": "test_product_metafield", "description": null, "created_at": "2023-04-14T10:31:29+00:00", "updated_at": "2023-04-14T10:31:29+00:00", "type": "product_reference", "admin_graphql_api_id": "gid://shopify/Metafield/22365729816765", "owner_id": 6796226560189, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953872775} +{"stream": "metafield_products", "data": {"id": 22365772251325, "namespace": "custom", "value": "Test", "key": "product_metafield_test_2", "description": null, "created_at": "2023-04-14T11:04:46+00:00", "updated_at": "2023-04-14T11:04:46+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365772251325", "owner_id": 6796229574845, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953872776} +{"stream": "metafield_product_variants", "data": {"id": 22365715955901, "namespace": "custom", "value": "Test Varia", "key": "test_variant_metafield", "description": null, "created_at": "2023-04-14T10:24:03+00:00", "updated_at": "2023-04-14T10:24:03+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365715955901", "owner_id": 41561961824445, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953885682} +{"stream": "metafield_product_variants", "data": {"id": 22365724082365, "namespace": "custom", "value": "Test Varia", "key": "test_variant_metafield", "description": null, "created_at": "2023-04-14T10:29:27+00:00", "updated_at": "2023-04-14T10:29:27+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365724082365", "owner_id": 42778150305981, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953885682} +{"stream": "metafield_product_variants", "data": {"id": 26493956391101, "namespace": "global", "value": "330510", "key": "harmonized_system_code", "description": null, "created_at": "2023-12-11T10:37:41+00:00", "updated_at": "2023-12-11T10:37:41+00:00", "type": "string", "admin_graphql_api_id": "gid://shopify/Metafield/26493956391101", "owner_id": 43315735396541, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953885683} +{"stream": "metafield_shops", "data": {"id": 19716782129341, "namespace": "inventory", "key": "warehouse", "value": "26", "description": null, "owner_id": 58033176765, "created_at": "2021-07-08T03:38:45-07:00", "updated_at": "2023-04-14T05:47:26-07:00", "owner_resource": "shop", "type": "number_integer", "admin_graphql_api_id": "gid://shopify/Metafield/19716782129341", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953886629} +{"stream": "metafield_shops", "data": {"id": 22534020104381, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 58033176765, "created_at": "2023-04-24T11:12:38-07:00", "updated_at": "2023-04-24T11:12:38-07:00", "owner_resource": "shop", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534020104381", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953886630} +{"stream": "metafield_smart_collections", "data": {"id": 21525604106429, "namespace": "my_fields", "key": "discount", "value": "50%", "description": null, "owner_id": 273278566589, "created_at": "2022-10-12T13:36:55-07:00", "updated_at": "2022-10-12T13:36:55-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21525604106429", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953888675} +{"stream": "metafield_smart_collections", "data": {"id": 22366265573565, "namespace": "my_fields", "key": "new_key", "value": "51%", "description": null, "owner_id": 273278566589, "created_at": "2023-04-14T05:21:58-07:00", "updated_at": "2023-04-14T05:21:58-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366265573565", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953888677} +{"stream": "order_refunds", "data": {"id": 852809646269, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "created_at": "2022-06-15T06:25:43-07:00", "note": null, "order_id": 4554821468349, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5721170968765, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "amount": "57.23", "authorization": null, "created_at": "2022-06-15T06:25:42-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 4554821468349, "parent_id": 5721110872253, "payment_id": "c25048437719229.2", "processed_at": "2022-06-15T06:25:42-07:00", "receipt": {"paid_amount": "57.23"}, "source_name": "1830279", "status": "success", "test": true, "user_id": null, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}}], "refund_line_items": [{"id": 363131404477, "line_item_id": 11406125564093, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 57.23, "subtotal_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": 1.77, "amount_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}, "discount_application_index": 0}]}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953889759} +{"stream": "order_refunds", "data": {"id": 845032358077, "admin_graphql_api_id": "gid://shopify/Refund/845032358077", "created_at": "2022-03-07T02:09:04-08:00", "note": null, "order_id": 4147980107965, "processed_at": "2022-03-07T02:09:04-08:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [], "refund_line_items": [{"id": 352716947645, "line_item_id": 10576771317949, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 27.0, "subtotal_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 10576771317949, "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 285, "name": "Red & Silver Fishing Lure - Plastic", "price": 27.0, "price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796218302653, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "Red & Silver Fishing Lure", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090580615357, "variant_inventory_management": "shopify", "variant_title": "Plastic", "vendor": "Harris - Hamill", "tax_lines": [], "duties": [], "discount_allocations": []}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953889761} +{"stream": "order_refunds", "data": {"id": 829538369725, "admin_graphql_api_id": "gid://shopify/Refund/829538369725", "created_at": "2021-09-21T05:31:59-07:00", "note": "test refund", "order_id": 3935377129661, "processed_at": "2021-09-21T05:31:59-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5189894406333, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5189894406333", "amount": "102.00", "authorization": null, "created_at": "2021-09-21T05:31:58-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 3935377129661, "parent_id": 4933790040253, "payment_id": "c21670281707709.2", "processed_at": "2021-09-21T05:31:58-07:00", "receipt": {"paid_amount": "102.00"}, "source_name": "1830279", "status": "success", "test": true, "user_id": 74861019325, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 11, "credit_card_expiration_year": 2023}}], "refund_line_items": [{"id": 332807864509, "line_item_id": 10130216452285, "location_id": 63590301885, "quantity": 1, "restock_type": "cancel", "subtotal": 102.0, "subtotal_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "line_item": {"id": 10130216452285, "admin_graphql_api_id": "gid://shopify/LineItem/10130216452285", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": null, "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953889762} +{"stream": "order_risks", "data": {"id": 6446736474301, "order_id": 4147980107965, "checkout_id": null, "source": "External", "score": 1.0, "recommendation": "cancel", "display": true, "cause_cancel": true, "message": "This order came from an anonymous proxy", "merchant_message": "This order came from an anonymous proxy", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953893694} +{"stream": "orders", "data": {"id": 5010584895677, "admin_graphql_api_id": "gid://shopify/Order/5010584895677", "app_id": 1354745, "browser_ip": "109.162.18.117", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 27351199088829, "checkout_token": "4064bfadc2457c9e15f2c7b4ee7ddb7d", "client_details": {"accept_language": null, "browser_height": null, "browser_ip": "109.162.18.117", "browser_width": null, "session_hash": null, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"}, "closed_at": "2023-04-13T05:09:46-07:00", "company": null, "confirmation_number": "ECI3YZGWP", "confirmed": true, "contact_email": null, "created_at": "2023-04-13T05:09:44-07:00", "currency": "USD", "current_subtotal_price": 102.0, "current_subtotal_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 102.0, "current_total_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "current_total_tax": 17.0, "current_total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "", "estimated_taxes": false, "financial_status": "paid", "fulfillment_status": "fulfilled", "landing_site": null, "landing_site_ref": null, "location_id": 63590301885, "merchant_of_record_app_id": null, "name": "#1143", "note": null, "note_attributes": [], "number": 143, "order_number": 1143, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/ad85969259bee7d4b380744934e67556/authenticate?key=cdd70808759b04f31c29975ba796fce9", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["manual"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2023-04-13T05:09:44-07:00", "reference": "b9344c8b118753db132edd503dc91515", "referring_site": null, "source_identifier": "b9344c8b118753db132edd503dc91515", "source_name": "shopify_draft_order", "source_url": null, "subtotal_price": 102.0, "subtotal_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "tags": "", "tax_exempt": false, "tax_lines": [{"price": 17.0, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "channel_liable": false}], "taxes_included": true, "test": false, "token": "ad85969259bee7d4b380744934e67556", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 102.0, "total_line_items_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 102.0, "total_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 63, "updated_at": "2023-04-13T05:09:50-07:00", "user_id": 74861019325, "billing_address": null, "customer": null, "discount_applications": [], "fulfillments": [{"id": 4451164913853, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451164913853", "created_at": "2023-04-13T05:09:45-07:00", "location_id": 63590301885, "name": "#1143.1", "order_id": 5010584895677, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:09:45-07:00", "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}]}], "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953896328} +{"stream": "orders", "data": {"id": 5010585911485, "admin_graphql_api_id": "gid://shopify/Order/5010585911485", "app_id": 1354745, "browser_ip": "109.162.18.117", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 27351203774653, "checkout_token": "117b35b4fd64c8de8d984830b72edfaf", "client_details": {"accept_language": null, "browser_height": null, "browser_ip": "109.162.18.117", "browser_width": null, "session_hash": null, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"}, "closed_at": "2023-04-13T05:11:17-07:00", "company": null, "confirmation_number": "CQPWZK5ZU", "confirmed": true, "contact_email": null, "created_at": "2023-04-13T05:11:15-07:00", "currency": "USD", "current_subtotal_price": 19.0, "current_subtotal_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 19.0, "current_total_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "current_total_tax": 3.17, "current_total_tax_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "", "estimated_taxes": false, "financial_status": "paid", "fulfillment_status": "fulfilled", "landing_site": null, "landing_site_ref": null, "location_id": 63590301885, "merchant_of_record_app_id": null, "name": "#1144", "note": null, "note_attributes": [], "number": 144, "order_number": 1144, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/a2d4a8a04fc6ec52a85f1811d269c88f/authenticate?key=a26b27cc1a040df3a1d7c67f6b14df75", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["manual"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2023-04-13T05:11:15-07:00", "reference": "f75c72a120e34e15a4dbc2d32315cc72", "referring_site": null, "source_identifier": "f75c72a120e34e15a4dbc2d32315cc72", "source_name": "shopify_draft_order", "source_url": null, "subtotal_price": 19.0, "subtotal_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "tags": "", "tax_exempt": false, "tax_lines": [{"price": 3.17, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "channel_liable": false}], "taxes_included": true, "test": false, "token": "a2d4a8a04fc6ec52a85f1811d269c88f", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 19.0, "total_line_items_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 19.0, "total_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 3.17, "total_tax_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 112, "updated_at": "2023-04-13T05:11:20-07:00", "user_id": 74861019325, "billing_address": null, "customer": null, "discount_applications": [], "fulfillments": [{"id": 4451169501373, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451169501373", "created_at": "2023-04-13T05:11:16-07:00", "location_id": 63590301885, "name": "#1144.1", "order_id": 5010585911485, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:11:16-07:00", "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": 19.0, "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}]}], "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": 19.0, "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953896336} +{"stream": "orders", "data": {"id": 4554821468349, "admin_graphql_api_id": "gid://shopify/Order/4554821468349", "app_id": 580111, "browser_ip": "176.113.167.23", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 25048437719229, "checkout_token": "cf5d16a0a0688905bd551c6dec591506", "client_details": {"accept_language": "en-US,en;q=0.9,uk;q=0.8", "browser_height": 754, "browser_ip": "176.113.167.23", "browser_width": 1519, "session_hash": null, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53"}, "closed_at": "2022-06-15T06:25:43-07:00", "company": null, "confirmation_number": null, "confirmed": true, "contact_email": "integration-test@airbyte.io", "created_at": "2022-06-15T05:16:53-07:00", "currency": "USD", "current_subtotal_price": 0.0, "current_subtotal_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 0.0, "current_total_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_tax": 0.0, "current_total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "integration-test@airbyte.io", "estimated_taxes": false, "financial_status": "refunded", "fulfillment_status": "fulfilled", "landing_site": "/wallets/checkouts.json", "landing_site_ref": null, "location_id": null, "merchant_of_record_app_id": null, "name": "#1136", "note": "updated_mon_24.04.2023", "note_attributes": [], "number": 136, "order_number": 1136, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/e4f98630ea44a884e33e700203ce2130/authenticate?key=edf087d6ae55a4541bf1375432f6a4b8", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["bogus"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2022-06-15T05:16:53-07:00", "reference": null, "referring_site": "https://airbyte-integration-test.myshopify.com/products/all-black-sneaker-right-foot", "source_identifier": null, "source_name": "web", "source_url": null, "subtotal_price": 57.23, "subtotal_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "tags": "Refund", "tax_exempt": false, "tax_lines": [], "taxes_included": true, "test": true, "token": "e4f98630ea44a884e33e700203ce2130", "total_discounts": 1.77, "total_discounts_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}, "total_line_items_price": 59.0, "total_line_items_price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 57.23, "total_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 0, "updated_at": "2023-04-24T07:00:37-07:00", "user_id": null, "billing_address": {"first_name": "Iryna", "address1": "2261 Market Street", "phone": null, "city": "San Francisco", "zip": "94114", "province": "California", "country": "United States", "last_name": "Grankova", "address2": "4381", "company": null, "latitude": 37.7647751, "longitude": -122.4320369, "name": "Iryna Grankova", "country_code": "US", "province_code": "CA"}, "customer": {"id": 5362027233469, "email": "integration-test@airbyte.io", "created_at": "2021-07-08T05:41:47-07:00", "updated_at": "2022-06-22T03:50:13-07:00", "first_name": "Airbyte", "last_name": "Team", "state": "disabled", "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "phone": null, "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "tags": "", "currency": "USD", "accepts_marketing": false, "accepts_marketing_updated_at": null, "marketing_opt_in_level": "single_opt_in", "tax_exemptions": [], "admin_graphql_api_id": "gid://shopify/Customer/5362027233469", "default_address": {"id": 7492260823229, "customer_id": 5362027233469, "first_name": "Airbyte", "last_name": "Team", "company": null, "address1": "2261 Market Street", "address2": "4381", "city": "San Francisco", "province": "California", "country": "United States", "zip": "94114", "phone": null, "name": "Airbyte Team", "province_code": "CA", "country_code": "US", "country_name": "United States", "default": true}}, "discount_applications": [{"target_type": "line_item", "type": "automatic", "value": "3.0", "value_type": "percentage", "allocation_method": "across", "target_selection": "all", "title": "eeeee"}], "fulfillments": [{"id": 4075788501181, "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "created_at": "2022-06-15T05:16:55-07:00", "location_id": 63590301885, "name": "#1136.1", "order_id": 4554821468349, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2022-06-15T05:16:55-07:00", "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}]}], "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}], "payment_terms": null, "refunds": [{"id": 852809646269, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "created_at": "2022-06-15T06:25:43-07:00", "note": null, "order_id": 4554821468349, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5721170968765, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "amount": "57.23", "authorization": null, "created_at": "2022-06-15T06:25:42-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 4554821468349, "parent_id": 5721110872253, "payment_id": "c25048437719229.2", "processed_at": "2022-06-15T06:25:42-07:00", "receipt": {"paid_amount": "57.23"}, "source_name": "1830279", "status": "success", "test": true, "user_id": null, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}}], "refund_line_items": [{"id": 363131404477, "line_item_id": 11406125564093, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 57.23, "subtotal_set": {"shop_money": {"amount": "57.23", "currency_code": "USD"}, "presentment_money": {"amount": "57.23", "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": "59.00", "price_set": {"shop_money": {"amount": "59.00", "currency_code": "USD"}, "presentment_money": {"amount": "59.00", "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}}], "duties": []}], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953896344} +{"stream": "pages", "data": {"id": 93795909821, "title": "Test Page", "shop_id": 58033176765, "handle": "test-page", "body_html": "Test Page 1", "author": null, "created_at": "2023-04-14T03:21:40-07:00", "updated_at": "2023-04-14T03:21:49-07:00", "published_at": "2023-04-14T03:21:40-07:00", "template_suffix": "", "admin_graphql_api_id": "gid://shopify/OnlineStorePage/93795909821", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953897896} +{"stream": "pages", "data": {"id": 83074252989, "title": "Warranty information", "shop_id": 58033176765, "handle": "warranty-information", "body_html": "updated_mon_24.04.2023", "author": "Shopify API", "created_at": "2021-07-08T05:19:00-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "published_at": "2021-07-08T05:19:00-07:00", "template_suffix": null, "admin_graphql_api_id": "gid://shopify/OnlineStorePage/83074252989", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953897896} +{"stream": "pages", "data": {"id": 95926616253, "deleted_at": "2023-09-06T03:37:06-07:00", "updated_at": "2023-09-06T03:37:06-07:00", "deleted_message": "Online Store deleted a page: Test Page for delete.", "deleted_description": "Online Store deleted a page: Test Page for delete.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953898431} +{"stream": "price_rules", "data": {"id": 1112171741373, "value_type": "fixed_amount", "value": "-10.0", "customer_selection": "all", "target_type": "line_item", "target_selection": "all", "allocation_method": "across", "allocation_limit": null, "once_per_customer": false, "usage_limit": null, "starts_at": "2017-01-19T09:59:10-08:00", "ends_at": null, "created_at": "2022-10-14T10:19:39-07:00", "updated_at": "2023-04-14T05:24:53-07:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": null, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "New Title 2023", "admin_graphql_api_id": "gid://shopify/PriceRule/1112171741373", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953899511} +{"stream": "price_rules", "data": {"id": 945000284349, "value_type": "percentage", "value": "-3.0", "customer_selection": "all", "target_type": "line_item", "target_selection": "all", "allocation_method": "across", "allocation_limit": null, "once_per_customer": true, "usage_limit": 10, "starts_at": "2021-07-07T07:22:04-07:00", "ends_at": null, "created_at": "2021-07-07T07:23:11-07:00", "updated_at": "2023-04-24T05:52:22-07:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": null, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "1V8Z165KSH5T", "admin_graphql_api_id": "gid://shopify/PriceRule/945000284349", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953899512} +{"stream": "price_rules", "data": {"id": 945205379261, "value_type": "percentage", "value": "-100.0", "customer_selection": "all", "target_type": "shipping_line", "target_selection": "all", "allocation_method": "each", "allocation_limit": null, "once_per_customer": false, "usage_limit": null, "starts_at": "2021-07-08T05:40:13-07:00", "ends_at": "2024-01-01T23:59:59-08:00", "created_at": "2021-07-08T05:40:37-07:00", "updated_at": "2023-12-07T03:40:44-08:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": {"greater_than_or_equal_to": "1.0"}, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "HZAVNV2487WC", "admin_graphql_api_id": "gid://shopify/PriceRule/945205379261", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953899513} +{"stream": "product_images", "data": {"id": 29301295481021, "alt": null, "position": 1, "product_id": 6796218138813, "created_at": "2021-06-22T18:09:28-07:00", "updated_at": "2021-06-22T18:09:28-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295481021", "width": 4393, "height": 2929, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/tin-of-beard-balm.jpg?v=1624410568", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953901149} +{"stream": "product_images", "data": {"id": 29301295513789, "alt": null, "position": 1, "product_id": 6796218269885, "created_at": "2021-06-22T18:09:29-07:00", "updated_at": "2021-06-22T18:09:29-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295513789", "width": 3840, "height": 2560, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/pair-of-all-black-sneakers.jpg?v=1624410569", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953901154} +{"stream": "product_images", "data": {"id": 29301295546557, "alt": null, "position": 1, "product_id": 6796218302653, "created_at": "2021-06-22T18:09:29-07:00", "updated_at": "2021-06-22T18:09:29-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295546557", "width": 3960, "height": 2640, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/red-silver-fishing-lure.jpg?v=1624410569", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953901155} +{"stream": "products", "data": {"id": 6796217909437, "title": "Red And Navy Tee Sleeve", "body_html": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "vendor": "Little Group", "product_type": "Movies", "created_at": "2021-06-22T18:09:27-07:00", "handle": "red-and-navy-tee-sleeve", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217909437", "variants": [{"id": 40090579992765, "product_id": 6796217909437, "title": "Plastic", "price": 23.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Plastic", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 39, "weight": 39.0, "weight_unit": "g", "inventory_item_id": 42185194700989, "inventory_quantity": 3, "old_inventory_quantity": 3, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579992765", "image_id": null}], "options": [{"id": 8720175235261, "product_id": 6796217909437, "name": "Title", "position": 1, "values": ["Plastic"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953903012} +{"stream": "products", "data": {"id": 6796217942205, "title": "Grey T-Shirt", "body_html": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "vendor": "Lang - Bogisich", "product_type": "Home", "created_at": "2021-06-22T18:09:27-07:00", "handle": "grey-t-shirt", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217942205", "variants": [{"id": 40090580025533, "product_id": 6796217942205, "title": "Granite", "price": 70.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Granite", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 0, "weight": 0.0, "weight_unit": "g", "inventory_item_id": 42185194733757, "inventory_quantity": 38, "old_inventory_quantity": 38, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580025533", "image_id": null}], "options": [{"id": 8720175268029, "product_id": 6796217942205, "name": "Title", "position": 1, "values": ["Granite"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953903015} +{"stream": "products", "data": {"id": 6796217974973, "title": "Pool Floaty Icecream", "body_html": "Inflatable pink ice cream pool toy.", "vendor": "Fritsch - Ferry", "product_type": "Grocery", "created_at": "2021-06-22T18:09:27-07:00", "handle": "pool-floaty-icecream", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217974973", "variants": [{"id": 40090580091069, "product_id": 6796217974973, "title": "magenta", "price": 57.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "magenta", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 499, "weight": 499.0, "weight_unit": "g", "inventory_item_id": 42185194766525, "inventory_quantity": 1, "old_inventory_quantity": 1, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580091069", "image_id": null}], "options": [{"id": 8720175300797, "product_id": 6796217974973, "name": "Title", "position": 1, "values": ["magenta"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953903015} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217843901", "title": "Lace Detail On Womens Top", "updatedAt": "2023-09-05T14:12:05Z", "createdAt": "2021-06-23T01:09:26Z", "publishedAt": null, "status": "ARCHIVED", "vendor": "Hayes, Hettinger and Hauck", "productType": "Beauty", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175169725", "name": "Title", "position": 1, "values": ["Soft"]}], "handle": "lace-detail-on-womens-top", "description": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "tracksInventory": true, "totalInventory": 12, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://2p5oyhnqeai50h4v-58033176765.shopifypreview.com/products_preview?preview_key=0684b80dc464e2ee090442093af4a856&_bt=eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaXRoYVhKaWVYUmxMV2x1ZEdWbmNtRjBhVzl1TFhSbGMzUXViWGx6YUc5d2FXWjVMbU52YlFZNkJrVlUiLCJleHAiOiIyMDI0LTAyLTI2VDE0OjI1OjA2LjQwMVoiLCJwdXIiOiJwZXJtYW5lbnRfcGFzc3dvcmRfYnlwYXNzIn19--7b63f2609629fadb3ba6b372b742a474055b5d14", "descriptionHtml": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "isGiftCard": false, "legacyResourceId": "6796217843901", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953906953} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217909437", "title": "Red And Navy Tee Sleeve", "updatedAt": "2023-04-20T11:12:25Z", "createdAt": "2021-06-23T01:09:27Z", "publishedAt": "2021-06-23T01:09:27Z", "status": "ACTIVE", "vendor": "Little Group", "productType": "Movies", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175235261", "name": "Title", "position": 1, "values": ["Plastic"]}], "handle": "red-and-navy-tee-sleeve", "description": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "tracksInventory": true, "totalInventory": 3, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://airbyte-integration-test.myshopify.com/products/red-and-navy-tee-sleeve", "descriptionHtml": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "isGiftCard": false, "legacyResourceId": "6796217909437", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953906955} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217942205", "title": "Grey T-Shirt", "updatedAt": "2023-04-20T11:12:25Z", "createdAt": "2021-06-23T01:09:27Z", "publishedAt": "2021-06-23T01:09:27Z", "status": "ACTIVE", "vendor": "Lang - Bogisich", "productType": "Home", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175268029", "name": "Title", "position": 1, "values": ["Granite"]}], "handle": "grey-t-shirt", "description": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "tracksInventory": true, "totalInventory": 38, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://airbyte-integration-test.myshopify.com/products/grey-t-shirt", "descriptionHtml": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "isGiftCard": false, "legacyResourceId": "6796217942205", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953906956} +{"stream": "product_variants", "data": {"id": 40090579992765, "product_id": 6796217909437, "title": "Plastic", "price": 23.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Plastic", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 39, "weight": 39.0, "weight_unit": "g", "inventory_item_id": 42185194700989, "inventory_quantity": 3, "old_inventory_quantity": 3, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579992765", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953908829} +{"stream": "product_variants", "data": {"id": 40090580025533, "product_id": 6796217942205, "title": "Granite", "price": 70.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Granite", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 0, "weight": 0.0, "weight_unit": "g", "inventory_item_id": 42185194733757, "inventory_quantity": 38, "old_inventory_quantity": 38, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580025533", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953908831} +{"stream": "product_variants", "data": {"id": 40090580091069, "product_id": 6796217974973, "title": "magenta", "price": 57.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "magenta", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 499, "weight": 499.0, "weight_unit": "g", "inventory_item_id": 42185194766525, "inventory_quantity": 1, "old_inventory_quantity": 1, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580091069", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953908832} +{"stream": "shop", "data": {"id": 58033176765, "name": "airbyte integration test", "email": "sherif@airbyte.io", "domain": "airbyte-integration-test.myshopify.com", "province": "California", "country": "US", "address1": "350 29th Avenue", "zip": "94121", "city": "San Francisco", "source": null, "phone": "8023494963", "latitude": 37.7827286, "longitude": -122.4889911, "primary_locale": "en", "address2": "", "created_at": "2021-06-22T18:00:23-07:00", "updated_at": "2024-01-30T21:11:05-08:00", "country_code": "US", "country_name": "United States", "currency": "USD", "customer_email": "sherif@airbyte.io", "timezone": "(GMT-08:00) America/Los_Angeles", "iana_timezone": "America/Los_Angeles", "shop_owner": "Airbyte Airbyte", "money_format": "${{amount}}", "money_with_currency_format": "${{amount}} USD", "weight_unit": "kg", "province_code": "CA", "taxes_included": true, "auto_configure_tax_inclusivity": null, "tax_shipping": null, "county_taxes": true, "plan_display_name": "Developer Preview", "plan_name": "partner_test", "has_discounts": true, "has_gift_cards": false, "myshopify_domain": "airbyte-integration-test.myshopify.com", "google_apps_domain": null, "google_apps_login_enabled": null, "money_in_emails_format": "${{amount}}", "money_with_currency_in_emails_format": "${{amount}} USD", "eligible_for_payments": true, "requires_extra_payments_agreement": false, "password_enabled": true, "has_storefront": true, "finances": true, "primary_location_id": 63590301885, "checkout_api_supported": true, "multi_location_enabled": true, "setup_required": false, "pre_launch_enabled": false, "enabled_presentment_currencies": ["USD"], "transactional_sms_disabled": false, "marketing_sms_consent_enabled_at_checkout": false, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953910990} +{"stream": "smart_collections", "data": {"id": 273278566589, "handle": "test-collection", "title": "Test Collection", "updated_at": "2023-09-05T07:12:04-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-07-19T07:02:54-07:00", "sort_order": "best-selling", "template_suffix": "", "disjunctive": false, "rules": ["{'column': 'type', 'relation': 'equals', 'condition': 'Beauty'}"], "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/273278566589", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953912019} +{"stream": "tender_transactions", "data": {"id": 4464009117885, "order_id": 5033391718589, "amount": "19.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-24T11:00:08-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953913062} +{"stream": "tender_transactions", "data": {"id": 4448993542333, "order_id": 5010585911485, "amount": "19.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-13T05:11:15-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953913064} +{"stream": "tender_transactions", "data": {"id": 4448992690365, "order_id": 5010584895677, "amount": "102.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-13T05:09:44-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953913065} +{"stream": "transactions", "data": {"id": 6281692217533, "error_code": null, "test": false, "kind": "SALE", "amount": 102.0, "receipt": "{}", "gateway": "manual", "authorization": null, "created_at": "2023-04-13T12:09:44+00:00", "status": "SUCCESS", "processed_at": "2023-04-13T12:09:44+00:00", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "payment_id": "r9BerEaVJ5OzQNmPGZsK2V7zq", "payment_details": null, "order_id": 5010584895677, "currency": "USD", "admin_graphql_api_id": "gid://shopify/OrderTransaction/6281692217533", "parent_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953920174} +{"stream": "transactions", "data": {"id": 6281693561021, "error_code": null, "test": false, "kind": "SALE", "amount": 19.0, "receipt": "{}", "gateway": "manual", "authorization": null, "created_at": "2023-04-13T12:11:15+00:00", "status": "SUCCESS", "processed_at": "2023-04-13T12:11:15+00:00", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "payment_id": "rguGpKMnZqzpEzPvDfnSS8x4B", "payment_details": null, "order_id": 5010585911485, "currency": "USD", "admin_graphql_api_id": "gid://shopify/OrderTransaction/6281693561021", "parent_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953920180} +{"stream": "transactions", "data": {"id": 6302086037693, "error_code": null, "test": false, "kind": "SALE", "amount": 19.0, "receipt": "{}", "gateway": "manual", "authorization": null, "created_at": "2023-04-24T18:00:08+00:00", "status": "SUCCESS", "processed_at": "2023-04-24T18:00:08+00:00", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "payment_id": "ru7Najsh1HavL8RRkZHavCzGe", "payment_details": null, "order_id": 5033391718589, "currency": "USD", "admin_graphql_api_id": "gid://shopify/OrderTransaction/6302086037693", "parent_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953920187} +{"stream": "customer_address", "data": {"address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "country": "United States", "country_code": "US", "company": "Test Company", "first_name": "New Test", "id": 8092523135165, "last_name": "Customer", "name": "New Test Customer", "phone": "", "province": "New Jersey", "province_code": "NJ", "zip": "07410", "customer_id": 6569096478909, "country_name": "United States", "default": true, "updated_at": "2023-04-24T13:53:48+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953929853} +{"stream": "customer_address", "data": {"address1": null, "address2": null, "city": null, "country": null, "country_code": null, "company": null, "first_name": "MArcos", "id": 8212915650749, "last_name": "Millnitz", "name": "MArcos Millnitz", "phone": null, "province": null, "province_code": null, "zip": null, "customer_id": 6676027932861, "country_name": null, "default": true, "updated_at": "2023-07-11T20:07:45+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953929855} +{"stream": "countries", "data": {"id": 417014841533, "name": "Rest of World", "code": "*", "tax_name": "Tax", "tax": 0.0, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953930918} +{"stream": "countries", "data": {"id": 417014808765, "name": "Ukraine", "code": "UA", "tax_name": "PDV", "tax": 0.2, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953930918} diff --git a/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records_transactions_with_user_id.jsonl b/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records_transactions_with_user_id.jsonl new file mode 100644 index 000000000000..37be336a3ed6 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/integration_tests/expected_records_transactions_with_user_id.jsonl @@ -0,0 +1,96 @@ +{"stream": "articles", "data": {"id": 558137508029, "title": "My new Article title", "created_at": "2022-10-07T16:09:02-07:00", "body_html": "

I like articles

\n

Yea, I like posting them through REST.

", "blog_id": 80417685693, "author": "John Smith", "user_id": null, "published_at": "2011-03-24T08:45:47-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "summary_html": null, "template_suffix": null, "handle": "my-new-article-title", "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558137508029", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953538863} +{"stream": "articles", "data": {"id": 558627979453, "title": "Test Blog Post", "created_at": "2023-04-14T03:19:02-07:00", "body_html": "Test Blog Post 1", "blog_id": 80417685693, "author": "Airbyte Airbyte", "user_id": "74861019325", "published_at": null, "updated_at": "2023-04-14T03:19:18-07:00", "summary_html": "", "template_suffix": "", "handle": "test-blog-post", "tags": "Has Been Tagged", "admin_graphql_api_id": "gid://shopify/OnlineStoreArticle/558627979453", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953538864} +{"stream": "articles", "data": {"id": 558999371965, "deleted_at": "2023-09-05T13:50:04-07:00", "updated_at": "2023-09-05T13:50:04-07:00", "deleted_message": "Online Store deleted an article: Test Article 1.", "deleted_description": "Online Store deleted an article: Test Article 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953539407} +{"stream": "blogs", "data": {"id": 80417685693, "handle": "news", "title": "News", "updated_at": "2023-09-05T14:02:00-07:00", "commentable": "no", "feedburner": null, "feedburner_location": null, "created_at": "2021-06-22T18:00:25-07:00", "template_suffix": null, "tags": "Has Been Tagged, This Post", "admin_graphql_api_id": "gid://shopify/OnlineStoreBlog/80417685693", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953541474} +{"stream": "blogs", "data": {"id": 85733114045, "deleted_at": "2023-09-06T03:30:22-07:00", "updated_at": "2023-09-06T03:30:22-07:00", "deleted_message": "Online Store deleted a blog: Test Blog 1.", "deleted_description": "Online Store deleted a blog: Test Blog 1.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953541999} +{"stream": "collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T14:06:59+00:00", "body_html": "updated_mon_24.04.2023", "sort_order": "BEST_SELLING", "template_suffix": "", "products_count": 1, "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "published_at": "2021-06-23T01:00:25+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953549142} +{"stream": "collections", "data": {"id": 273278566589, "handle": "test-collection", "title": "Test Collection", "updated_at": "2023-09-05T14:12:04+00:00", "body_html": "updated_mon_24.04.2023", "sort_order": "BEST_SELLING", "template_suffix": "", "products_count": 26, "admin_graphql_api_id": "gid://shopify/Collection/273278566589", "published_at": "2021-07-19T14:02:54+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953549142} +{"stream": "collects", "data": {"id": 29427031703741, "collection_id": 270889287869, "product_id": 6796220989629, "created_at": "2021-07-19T07:01:36-07:00", "updated_at": "2022-03-06T14:12:21-08:00", "position": 2, "sort_value": "0000000002", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953550149} +{"stream": "custom_collections", "data": {"id": 270889287869, "handle": "frontpage", "title": "Home page", "updated_at": "2023-09-05T07:06:59-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-06-22T18:00:25-07:00", "sort_order": "best-selling", "template_suffix": "", "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/270889287869", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953551166} +{"stream": "custom_collections", "data": {"id": 294253822141, "deleted_at": "2023-09-06T03:34:39-07:00", "updated_at": "2023-09-06T03:34:39-07:00", "deleted_message": "Airbyte Airbyte deleted a collection.", "deleted_description": "Airbyte Airbyte deleted a collection.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953551694} +{"stream": "customers", "data": {"id": 6569096478909, "email": "test@test.com", "created_at": "2023-04-13T02:30:04-07:00", "updated_at": "2023-04-24T06:53:48-07:00", "first_name": "New Test", "last_name": "Customer", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": "updated_mon_24.04.2023", "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": "+380639379992", "addresses": [{"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}], "accepts_marketing": true, "accepts_marketing_updated_at": "2023-04-13T02:30:04-07:00", "marketing_opt_in_level": "single_opt_in", "tax_exemptions": "[]", "email_marketing_consent": {"state": "subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": "2023-04-13T02:30:04-07:00"}, "sms_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null, "consent_collected_from": "SHOPIFY"}, "admin_graphql_api_id": "gid://shopify/Customer/6569096478909", "default_address": {"id": 8092523135165, "customer_id": 6569096478909, "first_name": "New Test", "last_name": "Customer", "company": "Test Company", "address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "province": "New Jersey", "country": "United States", "zip": "07410", "phone": "", "name": "New Test Customer", "province_code": "NJ", "country_code": "US", "country_name": "United States", "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953552788} +{"stream": "customers", "data": {"id": 6676027932861, "email": "marcos@airbyte.io", "created_at": "2023-07-11T13:07:45-07:00", "updated_at": "2023-07-11T13:07:45-07:00", "first_name": "MArcos", "last_name": "Millnitz", "orders_count": 0, "state": "disabled", "total_spent": 0.0, "last_order_id": null, "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "tags": "", "last_order_name": null, "currency": "USD", "phone": null, "addresses": [{"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}], "accepts_marketing": false, "accepts_marketing_updated_at": null, "marketing_opt_in_level": "single_opt_in", "tax_exemptions": "[]", "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "admin_graphql_api_id": "gid://shopify/Customer/6676027932861", "default_address": {"id": 8212915650749, "customer_id": 6676027932861, "first_name": "MArcos", "last_name": "Millnitz", "company": null, "address1": null, "address2": null, "city": null, "province": null, "country": null, "zip": null, "phone": null, "name": "MArcos Millnitz", "province_code": null, "country_code": null, "country_name": null, "default": true}, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953552789} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "updated_mon_24.04.2023", "id": 11539415990461, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/11539415990461", "price_rule_id": 945000284349, "updated_at": "2023-04-24T12:52:22+00:00", "created_at": "2021-07-07T14:23:11+00:00", "summary": "3% off entire order \u2022 One use per customer", "discount_type": "ORDER", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953559794} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "HZAVNV2487WC", "id": 11545139282109, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/11545139282109", "price_rule_id": 945205379261, "updated_at": "2023-12-07T11:40:44+00:00", "created_at": "2021-07-08T12:40:37+00:00", "summary": "Free shipping on all products \u2022 Minimum purchase of $1.00 \u2022 For all countries", "discount_type": "SHIPPING", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953559795} +{"stream": "discount_codes", "data": {"usage_count": 0, "code": "SUMMERSALE10OFF", "id": 13175793582269, "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/13175793582269", "price_rule_id": 945205379261, "updated_at": "2023-12-07T11:40:44+00:00", "created_at": "2021-07-08T12:40:37+00:00", "summary": "Free shipping on all products \u2022 Minimum purchase of $1.00 \u2022 For all countries", "discount_type": "SHIPPING", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953559795} +{"stream": "draft_orders", "data": {"id": 874683629757, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2021-07-02T00:50:29-07:00", "updated_at": "2023-04-14T05:16:33-07:00", "tax_exempt": false, "completed_at": "2021-07-02T00:51:50-07:00", "name": "#D2", "status": "completed", "line_items": [{"id": 57443281666237, "variant_id": 40090604011709, "product_id": 6796229509309, "title": "8 Ounce Soy Candle", "variant_title": "Wooden", "sku": "", "vendor": "Bosco Inc", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 63, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 17.0}], "applied_discount": null, "name": "8 Ounce Soy Candle - Wooden", "properties": [], "custom": false, "price": 102.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/57443281666237"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/e155e3254d0c0d64fa90587de417e0f3", "applied_discount": null, "order_id": 3935377129661, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 17.0}], "tags": "", "note_attributes": [], "total_price": "102.00", "subtotal_price": "102.00", "total_tax": "17.00", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/874683629757", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953561948} +{"stream": "draft_orders", "data": {"id": 929019691197, "note": "updated_mon_24.04.2023", "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2022-02-22T03:23:19-08:00", "updated_at": "2023-04-24T07:18:06-07:00", "tax_exempt": false, "completed_at": null, "name": "#D21", "status": "open", "line_items": [{"id": 58117295538365, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 2, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295538365"}, {"id": 58117295571133, "variant_id": null, "product_id": null, "title": "Test Item", "variant_title": null, "sku": null, "vendor": null, "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 1000, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 0.17}], "applied_discount": null, "name": "Test Item", "properties": [], "custom": true, "price": 1.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58117295571133"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/12893992cc01fc67935ab014fcf9300f", "applied_discount": null, "order_id": null, "shipping_line": {"title": "Test Shipping Fee", "custom": true, "handle": null, "price": 3.0}, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 6.33}, {"rate": 0.2, "title": "PDV", "price": 0.17}], "tags": "", "note_attributes": [], "total_price": "42.00", "subtotal_price": "39.00", "total_tax": "6.50", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/929019691197", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953561951} +{"stream": "draft_orders", "data": {"id": 987391033533, "note": null, "email": null, "taxes_included": true, "currency": "USD", "invoice_sent_at": null, "created_at": "2023-04-13T04:56:17-07:00", "updated_at": "2023-04-13T04:56:17-07:00", "tax_exempt": false, "completed_at": null, "name": "#D25", "status": "open", "line_items": [{"id": 58116862083261, "variant_id": 40090585923773, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Metal", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.16}], "applied_discount": null, "name": "4 Ounce Soy Candle - Metal", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862083261"}, {"id": 58116862116029, "variant_id": 41561955827901, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Test Variant 1", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Test Variant 1", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862116029"}, {"id": 58116862148797, "variant_id": 41561961824445, "product_id": 6796220989629, "title": "4 Ounce Soy Candle", "variant_title": "Test Variant 2", "sku": "", "vendor": "Hartmann Group", "quantity": 1, "requires_shipping": true, "taxable": true, "gift_card": false, "fulfillment_service": "manual", "grams": 112, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.17}], "applied_discount": null, "name": "4 Ounce Soy Candle - Test Variant 2", "properties": [], "custom": false, "price": 19.0, "admin_graphql_api_id": "gid://shopify/DraftOrderLineItem/58116862148797"}], "shipping_address": null, "billing_address": null, "invoice_url": "https://airbyte-integration-test.myshopify.com/58033176765/invoices/d193a965f7815817a2d37fddb30bfdb2", "applied_discount": null, "order_id": null, "shipping_line": null, "tax_lines": [{"rate": 0.2, "title": "PDV", "price": 3.16}, {"rate": 0.2, "title": "PDV", "price": 3.17}, {"rate": 0.2, "title": "PDV", "price": 3.17}], "tags": "", "note_attributes": [], "total_price": "57.00", "subtotal_price": "57.00", "total_tax": "9.50", "payment_terms": null, "admin_graphql_api_id": "gid://shopify/DraftOrder/987391033533", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953561952} +{"stream": "fulfillment_orders", "data": {"id": 5962451452093, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 431686549693, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-13T12:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-13T12:09:45+00:00", "updated_at": "2023-04-13T12:09:46+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5962451452093", "shop_id": 58033176765, "order_id": 5010584895677, "assigned_location_id": 63590301885, "line_items": [{"id": 12363725996221, "inventory_item_id": 42185218719933, "shop_id": 58033176765, "fulfillment_order_id": 5962451452093, "quantity": 1, "line_item_id": 12204214845629, "fulfillable_quantity": 0, "variant_id": 40090604011709}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953569038} +{"stream": "fulfillment_orders", "data": {"id": 5962452467901, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 431687532733, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-13T12:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-13T12:11:16+00:00", "updated_at": "2023-04-13T12:11:16+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5962452467901", "shop_id": 58033176765, "order_id": 5010585911485, "assigned_location_id": 63590301885, "line_items": [{"id": 12363727536317, "inventory_item_id": 43653688524989, "shop_id": 58033176765, "fulfillment_order_id": 5962452467901, "quantity": 1, "line_item_id": 12204216385725, "fulfillable_quantity": 0, "variant_id": 41561961824445}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953569039} +{"stream": "fulfillment_orders", "data": {"id": 5985636450493, "assigned_location": {"address1": "Heroiv UPA 72", "address2": null, "city": "Lviv", "country_code": "UA", "name": "Heroiv UPA 72", "phone": "", "province": null, "zip": "30100", "location_id": 63590301885}, "destination": null, "delivery_method": {"id": 442031046845, "method_type": "SHIPPING", "min_delivery_date_time": null, "max_delivery_date_time": null}, "fulfill_at": "2023-04-24T18:00:00+00:00", "fulfill_by": null, "international_duties": null, "fulfillment_holds": [], "created_at": "2023-04-24T18:00:09+00:00", "updated_at": "2023-04-24T18:00:09+00:00", "request_status": "UNSUBMITTED", "status": "CLOSED", "supported_actions": [], "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/5985636450493", "shop_id": 58033176765, "order_id": 5033391718589, "assigned_location_id": 63590301885, "line_items": [{"id": 12407122067645, "inventory_item_id": 43653688524989, "shop_id": 58033176765, "fulfillment_order_id": 5985636450493, "quantity": 1, "line_item_id": 12247585521853, "fulfillable_quantity": 0, "variant_id": 41561961824445}], "merchant_requests": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953569040} +{"stream": "fulfillments", "data": {"id": 4451164913853, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451164913853", "created_at": "2023-04-13T05:09:45-07:00", "location_id": 63590301885, "name": "#1143.1", "order_id": 5010584895677, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:09:45-07:00", "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": "102.00", "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953570024} +{"stream": "fulfillments", "data": {"id": 4451169501373, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451169501373", "created_at": "2023-04-13T05:11:16-07:00", "location_id": 63590301885, "name": "#1144.1", "order_id": 5010585911485, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:11:16-07:00", "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": "19.00", "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953570026} +{"stream": "fulfillments", "data": {"id": 4075788501181, "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "created_at": "2022-06-15T05:16:55-07:00", "location_id": 63590301885, "name": "#1136.1", "order_id": 4554821468349, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2022-06-15T05:16:55-07:00", "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": "59.00", "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953570027} +{"stream": "inventory_items", "data": {"id": 44871665713341, "country_code_of_origin": null, "harmonized_system_code": null, "province_code_of_origin": null, "updated_at": "2023-04-14T10:29:27+00:00", "created_at": "2023-04-14T10:29:27+00:00", "sku": "", "tracked": true, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/InventoryItem/44871665713341", "cost": 60.0, "country_harmonized_system_codes": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953577593} +{"stream": "inventory_items", "data": {"id": 45419395743933, "country_code_of_origin": "UA", "harmonized_system_code": "330510", "province_code_of_origin": null, "updated_at": "2023-12-11T10:37:41+00:00", "created_at": "2023-12-11T10:37:41+00:00", "sku": "123", "tracked": true, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/InventoryItem/45419395743933", "cost": 29.0, "country_harmonized_system_codes": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953577593} +{"stream": "inventory_levels", "data": {"id": "63590301885|42185200631997", "available": 15, "updated_at": "2023-04-13T12:00:55+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185200631997", "inventory_item_id": 42185200631997, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953584675} +{"stream": "inventory_levels", "data": {"id": "63590301885|42185218719933", "available": 8, "updated_at": "2023-04-13T12:09:45+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185218719933", "inventory_item_id": 42185218719933, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953584677} +{"stream": "inventory_levels", "data": {"id": "63590301885|43653688524989", "available": 0, "updated_at": "2023-04-24T18:00:10+00:00", "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=43653688524989", "inventory_item_id": 43653688524989, "location_id": 63590301885, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953584677} +{"stream": "locations", "data": {"id": 63590301885, "name": "Heroiv UPA 72", "address1": "Heroiv UPA 72", "address2": "", "city": "Lviv", "zip": "30100", "province": null, "country": "UA", "phone": "", "created_at": "2021-06-22T18:00:29-07:00", "updated_at": "2023-11-28T07:08:27-08:00", "country_code": "UA", "country_name": "Ukraine", "province_code": null, "legacy": false, "active": true, "admin_graphql_api_id": "gid://shopify/Location/63590301885", "localized_country_name": "Ukraine", "localized_province_name": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953585688} +{"stream": "metafield_articles", "data": {"id": 21519818162365, "namespace": "global", "key": "new", "value": "newvalue", "description": null, "owner_id": 558137508029, "created_at": "2022-10-07T16:09:02-07:00", "updated_at": "2022-10-07T16:09:02-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519818162365", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953587648} +{"stream": "metafield_articles", "data": {"id": 22365709992125, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Article Metafield", "description": null, "owner_id": 558137508029, "created_at": "2023-04-14T03:18:26-07:00", "updated_at": "2023-04-14T03:18:26-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365709992125", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953587649} +{"stream": "metafield_articles", "data": {"id": 22365710352573, "namespace": "custom", "key": "test_blog_post_metafield", "value": "Test Blog Post Metafiled", "description": null, "owner_id": 558627979453, "created_at": "2023-04-14T03:19:18-07:00", "updated_at": "2023-04-14T03:19:18-07:00", "owner_resource": "article", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710352573", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953588091} +{"stream": "metafield_blogs", "data": {"id": 21519428255933, "namespace": "some_fields", "key": "sponsor", "value": "Shopify", "description": null, "owner_id": 80417685693, "created_at": "2022-10-07T06:05:23-07:00", "updated_at": "2022-10-07T06:05:23-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21519428255933", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953590792} +{"stream": "metafield_blogs", "data": {"id": 22365710745789, "namespace": "custom", "key": "test_blog_metafield", "value": "Test Blog Metafield", "description": null, "owner_id": 80417685693, "created_at": "2023-04-14T03:20:20-07:00", "updated_at": "2023-04-14T03:20:20-07:00", "owner_resource": "blog", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365710745789", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953590794} +{"stream": "metafield_collections", "data": {"id": 22365707174077, "namespace": "custom", "value": "Test Collection Metafield", "key": "test_collection_metafield", "description": null, "created_at": "2023-04-14T10:15:30+00:00", "updated_at": "2023-04-14T10:15:30+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365707174077", "owner_id": 270889287869, "owner_resource": "collection", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953598420} +{"stream": "metafield_collections", "data": {"id": 22366265573565, "namespace": "my_fields", "value": "51%", "key": "new_key", "description": null, "created_at": "2023-04-14T12:21:58+00:00", "updated_at": "2023-04-14T12:21:58+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366265573565", "owner_id": 273278566589, "owner_resource": "collection", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953598428} +{"stream": "metafield_customers", "data": {"id": 22346893361341, "namespace": "custom", "value": "Teste\n", "key": "test_definition_list_1", "description": null, "created_at": "2023-04-13T11:50:10+00:00", "updated_at": "2023-04-13T11:50:10+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893361341", "owner_id": 6569096478909, "owner_resource": "customer", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953605731} +{"stream": "metafield_customers", "data": {"id": 22346893394109, "namespace": "custom", "value": "Taster", "key": "test_definition", "description": null, "created_at": "2023-04-13T11:50:10+00:00", "updated_at": "2023-04-13T11:50:10+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22346893394109", "owner_id": 6569096478909, "owner_resource": "customer", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953605732} +{"stream": "metafield_draft_orders", "data": {"id": 22366258528445, "namespace": "discounts", "value": "50%", "key": "hello", "description": null, "created_at": "2023-04-14T12:16:33+00:00", "updated_at": "2023-04-14T12:16:33+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366258528445", "owner_id": 874683629757, "owner_resource": "draft_order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953612753} +{"stream": "metafield_draft_orders", "data": {"id": 22532787175613, "namespace": "new_metafield", "value": "updated_mon_24.04.2023", "key": "new_metafield", "description": null, "created_at": "2023-04-24T14:18:06+00:00", "updated_at": "2023-04-24T14:18:06+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22532787175613", "owner_id": 929019691197, "owner_resource": "draft_order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953612755} +{"stream": "metafield_locations", "data": {"id": 26246034161853, "namespace": "custom", "value": "2023-11-28 updated", "key": "test_location_metafield", "description": null, "created_at": "2023-11-28T15:08:26+00:00", "updated_at": "2023-11-28T15:08:26+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/26246034161853", "owner_id": 63590301885, "owner_resource": "location", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953619903} +{"stream": "metafield_orders", "data": {"id": 22347288150205, "namespace": "my_fields", "value": "asdfasdf", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:09:50+00:00", "updated_at": "2023-04-13T12:09:50+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347288150205", "owner_id": 5010584895677, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953626961} +{"stream": "metafield_orders", "data": {"id": 22347288740029, "namespace": "my_fields", "value": "asdfasdfasdf", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:11:20+00:00", "updated_at": "2023-04-13T12:11:20+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347288740029", "owner_id": 5010585911485, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953626961} +{"stream": "metafield_orders", "data": {"id": 22347287855293, "namespace": "my_fields", "value": "trtrtr", "key": "purchase_order", "description": null, "created_at": "2023-04-13T12:09:08+00:00", "updated_at": "2023-04-13T12:09:08+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22347287855293", "owner_id": 4147980107965, "owner_resource": "order", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953626962} +{"stream": "metafield_pages", "data": {"id": 22365711499453, "namespace": "custom", "key": "test_page_metafield", "value": "Test Page Metafield", "description": null, "owner_id": 93795909821, "created_at": "2023-04-14T03:21:49-07:00", "updated_at": "2023-04-14T03:21:49-07:00", "owner_resource": "page", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365711499453", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953628925} +{"stream": "metafield_pages", "data": {"id": 22534014828733, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 83074252989, "created_at": "2023-04-24T11:08:41-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "owner_resource": "page", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534014828733", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953629370} +{"stream": "metafield_product_images", "data": {"id": 22365851517117, "namespace": "my_fields", "value": "natural coton", "key": "liner_material", "description": null, "created_at": "2023-04-14T11:59:27+00:00", "updated_at": "2023-04-14T11:59:27+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365851517117", "owner_id": 29301295481021, "owner_resource": "product_image", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953637175} +{"stream": "metafield_product_images", "data": {"id": 22533588451517, "namespace": "new_metafield", "value": "updated_mon_24.04.2023", "key": "new_metafield", "description": null, "created_at": "2023-04-24T17:32:19+00:00", "updated_at": "2023-04-24T17:32:19+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22533588451517", "owner_id": 29301297316029, "owner_resource": "product_image", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953637175} +{"stream": "metafield_products", "data": {"id": 22365729718461, "namespace": "custom", "value": "Test Product Metafield", "key": "product_metafield_test_2", "description": null, "created_at": "2023-04-14T10:31:19+00:00", "updated_at": "2023-04-14T10:31:19+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365729718461", "owner_id": 6796226560189, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953644458} +{"stream": "metafield_products", "data": {"id": 22365729816765, "namespace": "custom", "value": "gid://shopify/Product/6796229574845", "key": "test_product_metafield", "description": null, "created_at": "2023-04-14T10:31:29+00:00", "updated_at": "2023-04-14T10:31:29+00:00", "type": "product_reference", "admin_graphql_api_id": "gid://shopify/Metafield/22365729816765", "owner_id": 6796226560189, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953644459} +{"stream": "metafield_products", "data": {"id": 22365772251325, "namespace": "custom", "value": "Test", "key": "product_metafield_test_2", "description": null, "created_at": "2023-04-14T11:04:46+00:00", "updated_at": "2023-04-14T11:04:46+00:00", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365772251325", "owner_id": 6796229574845, "owner_resource": "product", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953644459} +{"stream": "metafield_product_variants", "data": {"id": 22365715955901, "namespace": "custom", "value": "Test Varia", "key": "test_variant_metafield", "description": null, "created_at": "2023-04-14T10:24:03+00:00", "updated_at": "2023-04-14T10:24:03+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365715955901", "owner_id": 41561961824445, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953657344} +{"stream": "metafield_product_variants", "data": {"id": 22365724082365, "namespace": "custom", "value": "Test Varia", "key": "test_variant_metafield", "description": null, "created_at": "2023-04-14T10:29:27+00:00", "updated_at": "2023-04-14T10:29:27+00:00", "type": "multi_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22365724082365", "owner_id": 42778150305981, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953657344} +{"stream": "metafield_product_variants", "data": {"id": 26493956391101, "namespace": "global", "value": "330510", "key": "harmonized_system_code", "description": null, "created_at": "2023-12-11T10:37:41+00:00", "updated_at": "2023-12-11T10:37:41+00:00", "type": "string", "admin_graphql_api_id": "gid://shopify/Metafield/26493956391101", "owner_id": 43315735396541, "owner_resource": "product_variant", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953657344} +{"stream": "metafield_shops", "data": {"id": 19716782129341, "namespace": "inventory", "key": "warehouse", "value": "26", "description": null, "owner_id": 58033176765, "created_at": "2021-07-08T03:38:45-07:00", "updated_at": "2023-04-14T05:47:26-07:00", "owner_resource": "shop", "type": "number_integer", "admin_graphql_api_id": "gid://shopify/Metafield/19716782129341", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953658313} +{"stream": "metafield_shops", "data": {"id": 22534020104381, "namespace": "new_metafield", "key": "new_metafield", "value": "updated_mon_24.04.2023", "description": null, "owner_id": 58033176765, "created_at": "2023-04-24T11:12:38-07:00", "updated_at": "2023-04-24T11:12:38-07:00", "owner_resource": "shop", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22534020104381", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953658314} +{"stream": "metafield_smart_collections", "data": {"id": 21525604106429, "namespace": "my_fields", "key": "discount", "value": "50%", "description": null, "owner_id": 273278566589, "created_at": "2022-10-12T13:36:55-07:00", "updated_at": "2022-10-12T13:36:55-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/21525604106429", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953660383} +{"stream": "metafield_smart_collections", "data": {"id": 22366265573565, "namespace": "my_fields", "key": "new_key", "value": "51%", "description": null, "owner_id": 273278566589, "created_at": "2023-04-14T05:21:58-07:00", "updated_at": "2023-04-14T05:21:58-07:00", "owner_resource": "collection", "type": "single_line_text_field", "admin_graphql_api_id": "gid://shopify/Metafield/22366265573565", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953660391} +{"stream": "order_refunds", "data": {"id": 852809646269, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "created_at": "2022-06-15T06:25:43-07:00", "note": null, "order_id": 4554821468349, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5721170968765, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "amount": "57.23", "authorization": null, "created_at": "2022-06-15T06:25:42-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 4554821468349, "parent_id": 5721110872253, "payment_id": "c25048437719229.2", "processed_at": "2022-06-15T06:25:42-07:00", "receipt": {"paid_amount": "57.23"}, "source_name": "1830279", "status": "success", "test": true, "user_id": null, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}}], "refund_line_items": [{"id": 363131404477, "line_item_id": 11406125564093, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 57.23, "subtotal_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": 1.77, "amount_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}, "discount_application_index": 0}]}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953661477} +{"stream": "order_refunds", "data": {"id": 845032358077, "admin_graphql_api_id": "gid://shopify/Refund/845032358077", "created_at": "2022-03-07T02:09:04-08:00", "note": null, "order_id": 4147980107965, "processed_at": "2022-03-07T02:09:04-08:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [], "refund_line_items": [{"id": 352716947645, "line_item_id": 10576771317949, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 27.0, "subtotal_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "line_item": {"id": 10576771317949, "admin_graphql_api_id": "gid://shopify/LineItem/10576771317949", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 285, "name": "Red & Silver Fishing Lure - Plastic", "price": 27.0, "price_set": {"shop_money": {"amount": 27.0, "currency_code": "USD"}, "presentment_money": {"amount": 27.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796218302653, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "Red & Silver Fishing Lure", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090580615357, "variant_inventory_management": "shopify", "variant_title": "Plastic", "vendor": "Harris - Hamill", "tax_lines": [], "duties": [], "discount_allocations": []}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953661479} +{"stream": "order_refunds", "data": {"id": 829538369725, "admin_graphql_api_id": "gid://shopify/Refund/829538369725", "created_at": "2021-09-21T05:31:59-07:00", "note": "test refund", "order_id": 3935377129661, "processed_at": "2021-09-21T05:31:59-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5189894406333, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5189894406333", "amount": "102.00", "authorization": null, "created_at": "2021-09-21T05:31:58-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 3935377129661, "parent_id": 4933790040253, "payment_id": "c21670281707709.2", "processed_at": "2021-09-21T05:31:58-07:00", "receipt": {"paid_amount": "102.00"}, "source_name": "1830279", "status": "success", "test": true, "user_id": 74861019325, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 11, "credit_card_expiration_year": 2023}}], "refund_line_items": [{"id": 332807864509, "line_item_id": 10130216452285, "location_id": 63590301885, "quantity": 1, "restock_type": "cancel", "subtotal": 102.0, "subtotal_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "line_item": {"id": 10130216452285, "admin_graphql_api_id": "gid://shopify/LineItem/10130216452285", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": null, "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}}], "duties": "[]", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953661480} +{"stream": "order_risks", "data": {"id": 6446736474301, "order_id": 4147980107965, "checkout_id": null, "source": "External", "score": 1.0, "recommendation": "cancel", "display": true, "cause_cancel": true, "message": "This order came from an anonymous proxy", "merchant_message": "This order came from an anonymous proxy", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953665729} +{"stream": "orders", "data": {"id": 5010584895677, "admin_graphql_api_id": "gid://shopify/Order/5010584895677", "app_id": 1354745, "browser_ip": "109.162.18.117", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 27351199088829, "checkout_token": "4064bfadc2457c9e15f2c7b4ee7ddb7d", "client_details": {"accept_language": null, "browser_height": null, "browser_ip": "109.162.18.117", "browser_width": null, "session_hash": null, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"}, "closed_at": "2023-04-13T05:09:46-07:00", "company": null, "confirmation_number": "ECI3YZGWP", "confirmed": true, "contact_email": null, "created_at": "2023-04-13T05:09:44-07:00", "currency": "USD", "current_subtotal_price": 102.0, "current_subtotal_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 102.0, "current_total_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "current_total_tax": 17.0, "current_total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "", "estimated_taxes": false, "financial_status": "paid", "fulfillment_status": "fulfilled", "landing_site": null, "landing_site_ref": null, "location_id": 63590301885, "merchant_of_record_app_id": null, "name": "#1143", "note": null, "note_attributes": [], "number": 143, "order_number": 1143, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/ad85969259bee7d4b380744934e67556/authenticate?key=cdd70808759b04f31c29975ba796fce9", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["manual"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2023-04-13T05:09:44-07:00", "reference": "b9344c8b118753db132edd503dc91515", "referring_site": null, "source_identifier": "b9344c8b118753db132edd503dc91515", "source_name": "shopify_draft_order", "source_url": null, "subtotal_price": 102.0, "subtotal_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "tags": "", "tax_exempt": false, "tax_lines": [{"price": 17.0, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "channel_liable": false}], "taxes_included": true, "test": false, "token": "ad85969259bee7d4b380744934e67556", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 102.0, "total_line_items_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 102.0, "total_price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 17.0, "total_tax_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 63, "updated_at": "2023-04-13T05:09:50-07:00", "user_id": 74861019325, "billing_address": null, "customer": null, "discount_applications": [], "fulfillments": [{"id": 4451164913853, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451164913853", "created_at": "2023-04-13T05:09:45-07:00", "location_id": 63590301885, "name": "#1143.1", "order_id": 5010584895677, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:09:45-07:00", "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}]}], "line_items": [{"id": 12204214845629, "admin_graphql_api_id": "gid://shopify/LineItem/12204214845629", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 63, "name": "8 Ounce Soy Candle - Wooden", "price": 102.0, "price_set": {"shop_money": {"amount": 102.0, "currency_code": "USD"}, "presentment_money": {"amount": 102.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796229509309, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "8 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090604011709, "variant_inventory_management": "shopify", "variant_title": "Wooden", "vendor": "Bosco Inc", "tax_lines": [{"channel_liable": false, "price": 17.0, "price_set": {"shop_money": {"amount": 17.0, "currency_code": "USD"}, "presentment_money": {"amount": 17.0, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953668490} +{"stream": "orders", "data": {"id": 5010585911485, "admin_graphql_api_id": "gid://shopify/Order/5010585911485", "app_id": 1354745, "browser_ip": "109.162.18.117", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 27351203774653, "checkout_token": "117b35b4fd64c8de8d984830b72edfaf", "client_details": {"accept_language": null, "browser_height": null, "browser_ip": "109.162.18.117", "browser_width": null, "session_hash": null, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"}, "closed_at": "2023-04-13T05:11:17-07:00", "company": null, "confirmation_number": "CQPWZK5ZU", "confirmed": true, "contact_email": null, "created_at": "2023-04-13T05:11:15-07:00", "currency": "USD", "current_subtotal_price": 19.0, "current_subtotal_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 19.0, "current_total_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "current_total_tax": 3.17, "current_total_tax_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "", "estimated_taxes": false, "financial_status": "paid", "fulfillment_status": "fulfilled", "landing_site": null, "landing_site_ref": null, "location_id": 63590301885, "merchant_of_record_app_id": null, "name": "#1144", "note": null, "note_attributes": [], "number": 144, "order_number": 1144, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/a2d4a8a04fc6ec52a85f1811d269c88f/authenticate?key=a26b27cc1a040df3a1d7c67f6b14df75", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["manual"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2023-04-13T05:11:15-07:00", "reference": "f75c72a120e34e15a4dbc2d32315cc72", "referring_site": null, "source_identifier": "f75c72a120e34e15a4dbc2d32315cc72", "source_name": "shopify_draft_order", "source_url": null, "subtotal_price": 19.0, "subtotal_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "tags": "", "tax_exempt": false, "tax_lines": [{"price": 3.17, "rate": 0.2, "title": "PDV", "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "channel_liable": false}], "taxes_included": true, "test": false, "token": "a2d4a8a04fc6ec52a85f1811d269c88f", "total_discounts": 0.0, "total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_line_items_price": 19.0, "total_line_items_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 19.0, "total_price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 3.17, "total_tax_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 112, "updated_at": "2023-04-13T05:11:20-07:00", "user_id": 74861019325, "billing_address": null, "customer": null, "discount_applications": [], "fulfillments": [{"id": 4451169501373, "admin_graphql_api_id": "gid://shopify/Fulfillment/4451169501373", "created_at": "2023-04-13T05:11:16-07:00", "location_id": 63590301885, "name": "#1144.1", "order_id": 5010585911485, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2023-04-13T05:11:16-07:00", "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": 19.0, "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}]}], "line_items": [{"id": 12204216385725, "admin_graphql_api_id": "gid://shopify/LineItem/12204216385725", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 112, "name": "4 Ounce Soy Candle - Test Variant 2", "price": 19.0, "price_set": {"shop_money": {"amount": 19.0, "currency_code": "USD"}, "presentment_money": {"amount": 19.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796220989629, "properties": [], "quantity": 1, "requires_shipping": true, "sku": "", "taxable": true, "title": "4 Ounce Soy Candle", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 41561961824445, "variant_inventory_management": "shopify", "variant_title": "Test Variant 2", "vendor": "Hartmann Group", "tax_lines": [{"channel_liable": false, "price": 3.17, "price_set": {"shop_money": {"amount": 3.17, "currency_code": "USD"}, "presentment_money": {"amount": 3.17, "currency_code": "USD"}}, "rate": 0.2, "title": "PDV"}], "duties": [], "discount_allocations": []}], "payment_terms": null, "refunds": [], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953668500} +{"stream": "orders", "data": {"id": 4554821468349, "admin_graphql_api_id": "gid://shopify/Order/4554821468349", "app_id": 580111, "browser_ip": "176.113.167.23", "buyer_accepts_marketing": false, "cancel_reason": null, "cancelled_at": null, "cart_token": null, "checkout_id": 25048437719229, "checkout_token": "cf5d16a0a0688905bd551c6dec591506", "client_details": {"accept_language": "en-US,en;q=0.9,uk;q=0.8", "browser_height": 754, "browser_ip": "176.113.167.23", "browser_width": 1519, "session_hash": null, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53"}, "closed_at": "2022-06-15T06:25:43-07:00", "company": null, "confirmation_number": null, "confirmed": true, "contact_email": "integration-test@airbyte.io", "created_at": "2022-06-15T05:16:53-07:00", "currency": "USD", "current_subtotal_price": 0.0, "current_subtotal_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_additional_fees_set": null, "current_total_discounts": 0.0, "current_total_discounts_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_duties_set": null, "current_total_price": 0.0, "current_total_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "current_total_tax": 0.0, "current_total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "customer_locale": "en", "device_id": null, "discount_codes": [], "email": "integration-test@airbyte.io", "estimated_taxes": false, "financial_status": "refunded", "fulfillment_status": "fulfilled", "landing_site": "/wallets/checkouts.json", "landing_site_ref": null, "location_id": null, "merchant_of_record_app_id": null, "name": "#1136", "note": "updated_mon_24.04.2023", "note_attributes": [], "number": 136, "order_number": 1136, "order_status_url": "https://airbyte-integration-test.myshopify.com/58033176765/orders/e4f98630ea44a884e33e700203ce2130/authenticate?key=edf087d6ae55a4541bf1375432f6a4b8", "original_total_additional_fees_set": null, "original_total_duties_set": null, "payment_gateway_names": ["bogus"], "phone": null, "po_number": null, "presentment_currency": "USD", "processed_at": "2022-06-15T05:16:53-07:00", "reference": null, "referring_site": "https://airbyte-integration-test.myshopify.com/products/all-black-sneaker-right-foot", "source_identifier": null, "source_name": "web", "source_url": null, "subtotal_price": 57.23, "subtotal_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "tags": "Refund", "tax_exempt": false, "tax_lines": [], "taxes_included": true, "test": true, "token": "e4f98630ea44a884e33e700203ce2130", "total_discounts": 1.77, "total_discounts_set": {"shop_money": {"amount": 1.77, "currency_code": "USD"}, "presentment_money": {"amount": 1.77, "currency_code": "USD"}}, "total_line_items_price": 59.0, "total_line_items_price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "total_outstanding": 0.0, "total_price": 57.23, "total_price_set": {"shop_money": {"amount": 57.23, "currency_code": "USD"}, "presentment_money": {"amount": 57.23, "currency_code": "USD"}}, "total_shipping_price_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "total_tip_received": 0.0, "total_weight": 0, "updated_at": "2023-04-24T07:00:37-07:00", "user_id": null, "billing_address": {"first_name": "Iryna", "address1": "2261 Market Street", "phone": null, "city": "San Francisco", "zip": "94114", "province": "California", "country": "United States", "last_name": "Grankova", "address2": "4381", "company": null, "latitude": 37.7647751, "longitude": -122.4320369, "name": "Iryna Grankova", "country_code": "US", "province_code": "CA"}, "customer": {"id": 5362027233469, "email": "integration-test@airbyte.io", "created_at": "2021-07-08T05:41:47-07:00", "updated_at": "2022-06-22T03:50:13-07:00", "first_name": "Airbyte", "last_name": "Team", "state": "disabled", "note": null, "verified_email": true, "multipass_identifier": null, "tax_exempt": false, "phone": null, "email_marketing_consent": {"state": "not_subscribed", "opt_in_level": "single_opt_in", "consent_updated_at": null}, "sms_marketing_consent": null, "tags": "", "currency": "USD", "accepts_marketing": false, "accepts_marketing_updated_at": null, "marketing_opt_in_level": "single_opt_in", "tax_exemptions": [], "admin_graphql_api_id": "gid://shopify/Customer/5362027233469", "default_address": {"id": 7492260823229, "customer_id": 5362027233469, "first_name": "Airbyte", "last_name": "Team", "company": null, "address1": "2261 Market Street", "address2": "4381", "city": "San Francisco", "province": "California", "country": "United States", "zip": "94114", "phone": null, "name": "Airbyte Team", "province_code": "CA", "country_code": "US", "country_name": "United States", "default": true}}, "discount_applications": [{"target_type": "line_item", "type": "automatic", "value": "3.0", "value_type": "percentage", "allocation_method": "across", "target_selection": "all", "title": "eeeee"}], "fulfillments": [{"id": 4075788501181, "admin_graphql_api_id": "gid://shopify/Fulfillment/4075788501181", "created_at": "2022-06-15T05:16:55-07:00", "location_id": 63590301885, "name": "#1136.1", "order_id": 4554821468349, "origin_address": {}, "receipt": {}, "service": "manual", "shipment_status": null, "status": "success", "tracking_company": null, "tracking_number": null, "tracking_numbers": [], "tracking_url": null, "tracking_urls": [], "updated_at": "2022-06-15T05:16:55-07:00", "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}]}], "line_items": [{"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": 59.0, "price_set": {"shop_money": {"amount": 59.0, "currency_code": "USD"}, "presentment_money": {"amount": 59.0, "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": 0.0, "total_discount_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}], "payment_terms": null, "refunds": [{"id": 852809646269, "admin_graphql_api_id": "gid://shopify/Refund/852809646269", "created_at": "2022-06-15T06:25:43-07:00", "note": null, "order_id": 4554821468349, "processed_at": "2022-06-15T06:25:43-07:00", "restock": true, "total_duties_set": {"shop_money": {"amount": 0.0, "currency_code": "USD"}, "presentment_money": {"amount": 0.0, "currency_code": "USD"}}, "user_id": 74861019325, "order_adjustments": [], "transactions": [{"id": 5721170968765, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721170968765", "amount": "57.23", "authorization": null, "created_at": "2022-06-15T06:25:42-07:00", "currency": "USD", "device_id": null, "error_code": null, "gateway": "bogus", "kind": "refund", "location_id": null, "message": "Bogus Gateway: Forced success", "order_id": 4554821468349, "parent_id": 5721110872253, "payment_id": "c25048437719229.2", "processed_at": "2022-06-15T06:25:42-07:00", "receipt": {"paid_amount": "57.23"}, "source_name": "1830279", "status": "success", "test": true, "user_id": null, "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}}], "refund_line_items": [{"id": 363131404477, "line_item_id": 11406125564093, "location_id": 63590301885, "quantity": 1, "restock_type": "return", "subtotal": 57.23, "subtotal_set": {"shop_money": {"amount": "57.23", "currency_code": "USD"}, "presentment_money": {"amount": "57.23", "currency_code": "USD"}}, "total_tax": 0.0, "total_tax_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "line_item": {"id": 11406125564093, "admin_graphql_api_id": "gid://shopify/LineItem/11406125564093", "fulfillable_quantity": 0, "fulfillment_service": "manual", "fulfillment_status": "fulfilled", "gift_card": false, "grams": 0, "name": "All Black Sneaker Right Foot - ivory", "price": "59.00", "price_set": {"shop_money": {"amount": "59.00", "currency_code": "USD"}, "presentment_money": {"amount": "59.00", "currency_code": "USD"}}, "product_exists": true, "product_id": 6796226560189, "properties": [], "quantity": 1, "requires_shipping": false, "sku": "", "taxable": true, "title": "All Black Sneaker Right Foot", "total_discount": "0.00", "total_discount_set": {"shop_money": {"amount": "0.00", "currency_code": "USD"}, "presentment_money": {"amount": "0.00", "currency_code": "USD"}}, "variant_id": 40090597884093, "variant_inventory_management": "shopify", "variant_title": "ivory", "vendor": "Becker - Moore", "tax_lines": [], "duties": [], "discount_allocations": [{"amount": "1.77", "amount_set": {"shop_money": {"amount": "1.77", "currency_code": "USD"}, "presentment_money": {"amount": "1.77", "currency_code": "USD"}}, "discount_application_index": 0}]}}], "duties": []}], "shipping_address": null, "shipping_lines": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953668502} +{"stream": "pages", "data": {"id": 93795909821, "title": "Test Page", "shop_id": 58033176765, "handle": "test-page", "body_html": "Test Page 1", "author": null, "created_at": "2023-04-14T03:21:40-07:00", "updated_at": "2023-04-14T03:21:49-07:00", "published_at": "2023-04-14T03:21:40-07:00", "template_suffix": "", "admin_graphql_api_id": "gid://shopify/OnlineStorePage/93795909821", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953670254} +{"stream": "pages", "data": {"id": 83074252989, "title": "Warranty information", "shop_id": 58033176765, "handle": "warranty-information", "body_html": "updated_mon_24.04.2023", "author": "Shopify API", "created_at": "2021-07-08T05:19:00-07:00", "updated_at": "2023-04-24T11:08:41-07:00", "published_at": "2021-07-08T05:19:00-07:00", "template_suffix": null, "admin_graphql_api_id": "gid://shopify/OnlineStorePage/83074252989", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953670255} +{"stream": "pages", "data": {"id": 95926616253, "deleted_at": "2023-09-06T03:37:06-07:00", "updated_at": "2023-09-06T03:37:06-07:00", "deleted_message": "Online Store deleted a page: Test Page for delete.", "deleted_description": "Online Store deleted a page: Test Page for delete.", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953670813} +{"stream": "price_rules", "data": {"id": 1112171741373, "value_type": "fixed_amount", "value": "-10.0", "customer_selection": "all", "target_type": "line_item", "target_selection": "all", "allocation_method": "across", "allocation_limit": null, "once_per_customer": false, "usage_limit": null, "starts_at": "2017-01-19T09:59:10-08:00", "ends_at": null, "created_at": "2022-10-14T10:19:39-07:00", "updated_at": "2023-04-14T05:24:53-07:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": null, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "New Title 2023", "admin_graphql_api_id": "gid://shopify/PriceRule/1112171741373", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953671890} +{"stream": "price_rules", "data": {"id": 945000284349, "value_type": "percentage", "value": "-3.0", "customer_selection": "all", "target_type": "line_item", "target_selection": "all", "allocation_method": "across", "allocation_limit": null, "once_per_customer": true, "usage_limit": 10, "starts_at": "2021-07-07T07:22:04-07:00", "ends_at": null, "created_at": "2021-07-07T07:23:11-07:00", "updated_at": "2023-04-24T05:52:22-07:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": null, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "1V8Z165KSH5T", "admin_graphql_api_id": "gid://shopify/PriceRule/945000284349", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953671890} +{"stream": "price_rules", "data": {"id": 945205379261, "value_type": "percentage", "value": "-100.0", "customer_selection": "all", "target_type": "shipping_line", "target_selection": "all", "allocation_method": "each", "allocation_limit": null, "once_per_customer": false, "usage_limit": null, "starts_at": "2021-07-08T05:40:13-07:00", "ends_at": "2024-01-01T23:59:59-08:00", "created_at": "2021-07-08T05:40:37-07:00", "updated_at": "2023-12-07T03:40:44-08:00", "entitled_product_ids": [], "entitled_variant_ids": [], "entitled_collection_ids": [], "entitled_country_ids": [], "prerequisite_product_ids": [], "prerequisite_variant_ids": [], "prerequisite_collection_ids": [], "customer_segment_prerequisite_ids": [], "prerequisite_customer_ids": [], "prerequisite_subtotal_range": {"greater_than_or_equal_to": "1.0"}, "prerequisite_quantity_range": null, "prerequisite_shipping_price_range": null, "prerequisite_to_entitlement_quantity_ratio": {"prerequisite_quantity": null, "entitled_quantity": null}, "prerequisite_to_entitlement_purchase": {"prerequisite_amount": null}, "title": "HZAVNV2487WC", "admin_graphql_api_id": "gid://shopify/PriceRule/945205379261", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953671891} +{"stream": "product_images", "data": {"id": 29301295481021, "alt": null, "position": 1, "product_id": 6796218138813, "created_at": "2021-06-22T18:09:28-07:00", "updated_at": "2021-06-22T18:09:28-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295481021", "width": 4393, "height": 2929, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/tin-of-beard-balm.jpg?v=1624410568", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953673537} +{"stream": "product_images", "data": {"id": 29301295513789, "alt": null, "position": 1, "product_id": 6796218269885, "created_at": "2021-06-22T18:09:29-07:00", "updated_at": "2021-06-22T18:09:29-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295513789", "width": 3840, "height": 2560, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/pair-of-all-black-sneakers.jpg?v=1624410569", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953673539} +{"stream": "product_images", "data": {"id": 29301295546557, "alt": null, "position": 1, "product_id": 6796218302653, "created_at": "2021-06-22T18:09:29-07:00", "updated_at": "2021-06-22T18:09:29-07:00", "admin_graphql_api_id": "gid://shopify/ProductImage/29301295546557", "width": 3960, "height": 2640, "src": "https://cdn.shopify.com/s/files/1/0580/3317/6765/products/red-silver-fishing-lure.jpg?v=1624410569", "variant_ids": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953673539} +{"stream": "products", "data": {"id": 6796217909437, "title": "Red And Navy Tee Sleeve", "body_html": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "vendor": "Little Group", "product_type": "Movies", "created_at": "2021-06-22T18:09:27-07:00", "handle": "red-and-navy-tee-sleeve", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217909437", "variants": [{"id": 40090579992765, "product_id": 6796217909437, "title": "Plastic", "price": 23.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Plastic", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 39, "weight": 39.0, "weight_unit": "g", "inventory_item_id": 42185194700989, "inventory_quantity": 3, "old_inventory_quantity": 3, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579992765", "image_id": null}], "options": [{"id": 8720175235261, "product_id": 6796217909437, "name": "Title", "position": 1, "values": ["Plastic"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953675398} +{"stream": "products", "data": {"id": 6796217942205, "title": "Grey T-Shirt", "body_html": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "vendor": "Lang - Bogisich", "product_type": "Home", "created_at": "2021-06-22T18:09:27-07:00", "handle": "grey-t-shirt", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217942205", "variants": [{"id": 40090580025533, "product_id": 6796217942205, "title": "Granite", "price": 70.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Granite", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 0, "weight": 0.0, "weight_unit": "g", "inventory_item_id": 42185194733757, "inventory_quantity": 38, "old_inventory_quantity": 38, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580025533", "image_id": null}], "options": [{"id": 8720175268029, "product_id": 6796217942205, "name": "Title", "position": 1, "values": ["Granite"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953675399} +{"stream": "products", "data": {"id": 6796217974973, "title": "Pool Floaty Icecream", "body_html": "Inflatable pink ice cream pool toy.", "vendor": "Fritsch - Ferry", "product_type": "Grocery", "created_at": "2021-06-22T18:09:27-07:00", "handle": "pool-floaty-icecream", "updated_at": "2023-04-20T04:12:25-07:00", "published_at": "2021-06-22T18:09:27-07:00", "template_suffix": null, "published_scope": "web", "tags": "developer-tools-generator", "status": "active", "admin_graphql_api_id": "gid://shopify/Product/6796217974973", "variants": [{"id": 40090580091069, "product_id": 6796217974973, "title": "magenta", "price": 57.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "magenta", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 499, "weight": 499.0, "weight_unit": "g", "inventory_item_id": 42185194766525, "inventory_quantity": 1, "old_inventory_quantity": 1, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580091069", "image_id": null}], "options": [{"id": 8720175300797, "product_id": 6796217974973, "name": "Title", "position": 1, "values": ["magenta"]}], "images": [], "image": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953675399} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217843901", "title": "Lace Detail On Womens Top", "updatedAt": "2023-09-05T14:12:05Z", "createdAt": "2021-06-23T01:09:26Z", "publishedAt": null, "status": "ARCHIVED", "vendor": "Hayes, Hettinger and Hauck", "productType": "Beauty", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175169725", "name": "Title", "position": 1, "values": ["Soft"]}], "handle": "lace-detail-on-womens-top", "description": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "tracksInventory": true, "totalInventory": 12, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://2p5oyhnqeai50h4v-58033176765.shopifypreview.com/products_preview?preview_key=49fdc517904f477196144662c8ad7b8f&_bt=eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaXRoYVhKaWVYUmxMV2x1ZEdWbmNtRjBhVzl1TFhSbGMzUXViWGx6YUc5d2FXWjVMbU52YlFZNkJrVlUiLCJleHAiOiIyMDI0LTAyLTI2VDE0OjIxOjE5LjAyOVoiLCJwdXIiOiJwZXJtYW5lbnRfcGFzc3dvcmRfYnlwYXNzIn19--a4d2e3e622f6ab0bcd3820bf524f8f50b65c14d7", "descriptionHtml": "A close-up side view of a woman's off-white shirt shows the design detail in the lace.", "isGiftCard": false, "legacyResourceId": "6796217843901", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953679676} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217909437", "title": "Red And Navy Tee Sleeve", "updatedAt": "2023-04-20T11:12:25Z", "createdAt": "2021-06-23T01:09:27Z", "publishedAt": "2021-06-23T01:09:27Z", "status": "ACTIVE", "vendor": "Little Group", "productType": "Movies", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175235261", "name": "Title", "position": 1, "values": ["Plastic"]}], "handle": "red-and-navy-tee-sleeve", "description": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "tracksInventory": true, "totalInventory": 3, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://airbyte-integration-test.myshopify.com/products/red-and-navy-tee-sleeve", "descriptionHtml": "Zoom in on the sleeve of a red t-shirt with navy blue trim along the sleeve. Looks like a great tennis outfit.", "isGiftCard": false, "legacyResourceId": "6796217909437", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953679682} +{"stream": "products_graph_ql", "data": {"id": "gid://shopify/Product/6796217942205", "title": "Grey T-Shirt", "updatedAt": "2023-04-20T11:12:25Z", "createdAt": "2021-06-23T01:09:27Z", "publishedAt": "2021-06-23T01:09:27Z", "status": "ACTIVE", "vendor": "Lang - Bogisich", "productType": "Home", "tags": ["developer-tools-generator"], "options": [{"id": "gid://shopify/ProductOption/8720175268029", "name": "Title", "position": 1, "values": ["Granite"]}], "handle": "grey-t-shirt", "description": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "tracksInventory": true, "totalInventory": 38, "totalVariants": 1, "onlineStoreUrl": null, "onlineStorePreviewUrl": "https://airbyte-integration-test.myshopify.com/products/grey-t-shirt", "descriptionHtml": "A grey t-shirt on a hanger. Simple. Classic. Grey.", "isGiftCard": false, "legacyResourceId": "6796217942205", "mediaCount": 0, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953679683} +{"stream": "product_variants", "data": {"id": 40090579992765, "product_id": 6796217909437, "title": "Plastic", "price": 23.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Plastic", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 39, "weight": 39.0, "weight_unit": "g", "inventory_item_id": 42185194700989, "inventory_quantity": 3, "old_inventory_quantity": 3, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090579992765", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953681543} +{"stream": "product_variants", "data": {"id": 40090580025533, "product_id": 6796217942205, "title": "Granite", "price": 70.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "Granite", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 0, "weight": 0.0, "weight_unit": "g", "inventory_item_id": 42185194733757, "inventory_quantity": 38, "old_inventory_quantity": 38, "requires_shipping": false, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580025533", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953681544} +{"stream": "product_variants", "data": {"id": 40090580091069, "product_id": 6796217974973, "title": "magenta", "price": 57.0, "sku": "", "position": 1, "inventory_policy": "deny", "compare_at_price": null, "fulfillment_service": "manual", "inventory_management": "shopify", "option1": "magenta", "option2": null, "option3": null, "created_at": "2021-06-22T18:09:27-07:00", "updated_at": "2023-10-27T09:55:54-07:00", "taxable": true, "barcode": null, "grams": 499, "weight": 499.0, "weight_unit": "g", "inventory_item_id": 42185194766525, "inventory_quantity": 1, "old_inventory_quantity": 1, "requires_shipping": true, "admin_graphql_api_id": "gid://shopify/ProductVariant/40090580091069", "image_id": null, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953681544} +{"stream": "shop", "data": {"id": 58033176765, "name": "airbyte integration test", "email": "sherif@airbyte.io", "domain": "airbyte-integration-test.myshopify.com", "province": "California", "country": "US", "address1": "350 29th Avenue", "zip": "94121", "city": "San Francisco", "source": null, "phone": "8023494963", "latitude": 37.7827286, "longitude": -122.4889911, "primary_locale": "en", "address2": "", "created_at": "2021-06-22T18:00:23-07:00", "updated_at": "2024-01-30T21:11:05-08:00", "country_code": "US", "country_name": "United States", "currency": "USD", "customer_email": "sherif@airbyte.io", "timezone": "(GMT-08:00) America/Los_Angeles", "iana_timezone": "America/Los_Angeles", "shop_owner": "Airbyte Airbyte", "money_format": "${{amount}}", "money_with_currency_format": "${{amount}} USD", "weight_unit": "kg", "province_code": "CA", "taxes_included": true, "auto_configure_tax_inclusivity": null, "tax_shipping": null, "county_taxes": true, "plan_display_name": "Developer Preview", "plan_name": "partner_test", "has_discounts": true, "has_gift_cards": false, "myshopify_domain": "airbyte-integration-test.myshopify.com", "google_apps_domain": null, "google_apps_login_enabled": null, "money_in_emails_format": "${{amount}}", "money_with_currency_in_emails_format": "${{amount}} USD", "eligible_for_payments": true, "requires_extra_payments_agreement": false, "password_enabled": true, "has_storefront": true, "finances": true, "primary_location_id": 63590301885, "checkout_api_supported": true, "multi_location_enabled": true, "setup_required": false, "pre_launch_enabled": false, "enabled_presentment_currencies": ["USD"], "transactional_sms_disabled": false, "marketing_sms_consent_enabled_at_checkout": false, "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953683813} +{"stream": "smart_collections", "data": {"id": 273278566589, "handle": "test-collection", "title": "Test Collection", "updated_at": "2023-09-05T07:12:04-07:00", "body_html": "updated_mon_24.04.2023", "published_at": "2021-07-19T07:02:54-07:00", "sort_order": "best-selling", "template_suffix": "", "disjunctive": false, "rules": ["{'column': 'type', 'relation': 'equals', 'condition': 'Beauty'}"], "published_scope": "web", "admin_graphql_api_id": "gid://shopify/Collection/273278566589", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953684911} +{"stream": "tender_transactions", "data": {"id": 4464009117885, "order_id": 5033391718589, "amount": "19.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-24T11:00:08-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953685992} +{"stream": "tender_transactions", "data": {"id": 4448993542333, "order_id": 5010585911485, "amount": "19.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-13T05:11:15-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953685994} +{"stream": "tender_transactions", "data": {"id": 4448992690365, "order_id": 5010584895677, "amount": "102.00", "currency": "USD", "user_id": null, "test": false, "processed_at": "2023-04-13T05:09:44-07:00", "remote_reference": null, "payment_details": null, "payment_method": "other", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953685995} +{"stream": "transactions", "data": {"id": 6281692217533, "order_id": 5010584895677, "kind": "sale", "gateway": "manual", "status": "success", "message": "Marked the manual payment as received", "created_at": "2023-04-13T05:09:44-07:00", "test": false, "authorization": null, "location_id": null, "user_id": null, "parent_id": null, "processed_at": "2023-04-13T05:09:44-07:00", "device_id": null, "error_code": null, "source_name": "checkout_one", "receipt": {}, "amount": 102.0, "currency": "USD", "payment_id": "r9BerEaVJ5OzQNmPGZsK2V7zq", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/6281692217533", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953688151} +{"stream": "transactions", "data": {"id": 6281693561021, "order_id": 5010585911485, "kind": "sale", "gateway": "manual", "status": "success", "message": "Marked the manual payment as received", "created_at": "2023-04-13T05:11:15-07:00", "test": false, "authorization": null, "location_id": null, "user_id": null, "parent_id": null, "processed_at": "2023-04-13T05:11:15-07:00", "device_id": null, "error_code": null, "source_name": "checkout_one", "receipt": {}, "amount": 19.0, "currency": "USD", "payment_id": "rguGpKMnZqzpEzPvDfnSS8x4B", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/6281693561021", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953688613} +{"stream": "transactions", "data": {"id": 5721110872253, "order_id": 4554821468349, "kind": "sale", "gateway": "bogus", "status": "success", "message": "Bogus Gateway: Forced success", "created_at": "2022-06-15T05:16:52-07:00", "test": true, "authorization": "53433", "location_id": null, "user_id": null, "parent_id": null, "processed_at": "2022-06-15T05:16:52-07:00", "device_id": null, "error_code": null, "source_name": "580111", "payment_details": {"credit_card_bin": "1", "avs_result_code": null, "cvv_result_code": null, "credit_card_number": "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 1", "credit_card_company": "Bogus", "buyer_action_info": null, "credit_card_name": "Bogus Gateway", "credit_card_wallet": null, "credit_card_expiration_month": 2, "credit_card_expiration_year": 2025}, "receipt": {"paid_amount": "57.23"}, "amount": 57.23, "currency": "USD", "payment_id": "c25048437719229.1", "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, "admin_graphql_api_id": "gid://shopify/OrderTransaction/5721110872253", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953689123} +{"stream": "customer_address", "data": {"address1": "My Best Accent", "address2": "", "city": "Fair Lawn", "country": "United States", "country_code": "US", "company": "Test Company", "first_name": "New Test", "id": 8092523135165, "last_name": "Customer", "name": "New Test Customer", "phone": "", "province": "New Jersey", "province_code": "NJ", "zip": "07410", "customer_id": 6569096478909, "country_name": "United States", "default": true, "updated_at": "2023-04-24T13:53:48+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953700866} +{"stream": "customer_address", "data": {"address1": null, "address2": null, "city": null, "country": null, "country_code": null, "company": null, "first_name": "MArcos", "id": 8212915650749, "last_name": "Millnitz", "name": "MArcos Millnitz", "phone": null, "province": null, "province_code": null, "zip": null, "customer_id": 6676027932861, "country_name": null, "default": true, "updated_at": "2023-07-11T20:07:45+00:00", "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953700867} +{"stream": "countries", "data": {"id": 417014841533, "name": "Rest of World", "code": "*", "tax_name": "Tax", "tax": 0.0, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953701837} +{"stream": "countries", "data": {"id": 417014808765, "name": "Ukraine", "code": "UA", "tax_name": "PDV", "tax": 0.2, "provinces": [], "shop_url": "airbyte-integration-test"}, "emitted_at": 1708953701838} diff --git a/airbyte-integrations/connectors/source-shopify/integration_tests/state.json b/airbyte-integrations/connectors/source-shopify/integration_tests/state.json index 25734860ba98..c29ae675c6c5 100644 --- a/airbyte-integrations/connectors/source-shopify/integration_tests/state.json +++ b/airbyte-integrations/connectors/source-shopify/integration_tests/state.json @@ -174,13 +174,13 @@ "updated_at": "2023-04-14T04:04:46-07:00" }, "product_images": { - "id": 33290489659581, "products": { - "updated_at": "", + "updated_at": "2023-04-24T11:05:13-07:00", "deleted": { "deleted_at": "2023-09-05T13:32:22-07:00" } - } + }, + "updated_at": "2023-04-24T10:27:15-07:00" }, "metafield_product_images": { "products": { diff --git a/airbyte-integrations/connectors/source-shopify/metadata.yaml b/airbyte-integrations/connectors/source-shopify/metadata.yaml index 0eb582dd457d..a1881ee5550b 100644 --- a/airbyte-integrations/connectors/source-shopify/metadata.yaml +++ b/airbyte-integrations/connectors/source-shopify/metadata.yaml @@ -11,7 +11,7 @@ data: connectorSubtype: api connectorType: source definitionId: 9da77001-af33-4bcd-be46-6252bf9342b9 - dockerImageTag: 1.1.8 + dockerImageTag: 2.0.0 dockerRepository: airbyte/source-shopify documentationUrl: https://docs.airbyte.com/integrations/sources/shopify githubIssueLabel: source-shopify @@ -35,11 +35,37 @@ data: "This upgrade brings changes to certain streams after migration to Shopify API version `2023-07`, more details in this PR: https://github.com/airbytehq/airbyte/pull/29361." upgradeDeadline: "2023-09-17" + 2.0.0: + message: "This upgrade brings perfomance impovements and stream schema changes. Details are available here: https://github.com/airbytehq/airbyte/pull/32345#issue-1985556333." + upgradeDeadline: "2024-03-18" + scopedImpact: + - scopeType: stream + impactedScopes: + [ + "collections", + "customer_address", + "discount_codes", + "fulfillment_orders", + "fulfillments", + "inventory_items", + "inventory_levels", + "metafield_collections", + "metafield_customers", + "metafield_draft_orders", + "metafield_locations", + "metafield_orders", + "metafield_product_images", + "metafield_product_variants", + "order_refunds", + "product_images", + "product_variants", + "transactions", + ] suggestedStreams: streams: - customers - order_refunds - - transactions + - transactions_graphql - product_variants - abandoned_checkouts - discount_codes @@ -50,7 +76,6 @@ data: - inventory_levels - custom_collections - fulfillments - - order_risks - products_graph_ql - product_images - collects diff --git a/airbyte-integrations/connectors/source-shopify/poetry.lock b/airbyte-integrations/connectors/source-shopify/poetry.lock index faca58b052f6..ea5d5de6d857 100644 --- a/airbyte-integrations/connectors/source-shopify/poetry.lock +++ b/airbyte-integrations/connectors/source-shopify/poetry.lock @@ -312,6 +312,26 @@ files = [ {file = "graphql_core-3.2.3-py3-none-any.whl", hash = "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3"}, ] +[[package]] +name = "graphql-query" +version = "1.1.1" +description = "Complete GraphQL query string generation for python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "graphql_query-1.1.1-py3-none-any.whl", hash = "sha256:c88e052d5739cbc0c20ed4597892025b2e3c363c75b44a06ea55005f09ecbd3d"}, + {file = "graphql_query-1.1.1.tar.gz", hash = "sha256:b0f52b560977fdf48c5ca48bb35772d86632018e13e948b10681815a58945b07"}, +] + +[package.dependencies] +jinja2 = ">=3.1,<3.2" +pydantic = ">=1.10,<1.11" + +[package.extras] +dev = ["black", "mypy", "pylint-pydantic", "ruff", "wheel"] +docs = ["sphinx", "sphinx-argparse", "sphinx-rtd-theme", "sphinxcontrib-github"] +test = ["pytest", "pytest-cov", "pytest-mock"] + [[package]] name = "idna" version = "3.6" @@ -1037,4 +1057,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.9,<3.12" -content-hash = "71f6b166e4220683dea93a273110eca25f9680be5842ee802d78a9583f31ee2f" +content-hash = "d5eb24b58b8ae8d10cc9f421ea1d125ef3833c69a1007e13624990a30bf2070a" diff --git a/airbyte-integrations/connectors/source-shopify/pyproject.toml b/airbyte-integrations/connectors/source-shopify/pyproject.toml index 65ae0c202895..e26cb727a7e7 100644 --- a/airbyte-integrations/connectors/source-shopify/pyproject.toml +++ b/airbyte-integrations/connectors/source-shopify/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "1.1.8" +version = "2.0.0" name = "source-shopify" description = "Source CDK implementation for Shopify." authors = [ "Airbyte ",] @@ -19,6 +19,7 @@ include = "source_shopify" python = "^3.9,<3.12" airbyte-cdk = "==0.59.0" sgqlc = "==16.3" +graphql-query = "^1.1.1" [tool.poetry.scripts] source-shopify = "source_shopify.run:run" diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/auth.py b/airbyte-integrations/connectors/source-shopify/source_shopify/auth.py index cba5ea272f26..6d53197ff18a 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/auth.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/auth.py @@ -34,7 +34,6 @@ def __init__(self, config: Mapping[str, Any]): self.config = config def get_auth_header(self) -> Mapping[str, Any]: - auth_header: str = "X-Shopify-Access-Token" credentials: Dict = self.config.get("credentials", self.config.get("auth_method")) auth_method: str = credentials.get("auth_method") diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customer_address.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customer_address.json index 31d24b3c458c..a2e9af21f4fc 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customer_address.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customer_address.json @@ -55,6 +55,10 @@ }, "shop_url": { "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"], + "format": "date-time" } } } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customers.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customers.json index 3baa26ec8d73..c78b7ee47494 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customers.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/customers.json @@ -214,6 +214,9 @@ "sms_marketing_consent": { "type": ["null", "object"], "properties": { + "consent_collected_from": { + "type": ["null", "string"] + }, "consent_updated_at": { "type": ["null", "string"], "format": "date-time" diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/discount_codes.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/discount_codes.json index f3e208e014c5..4b864604d486 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/discount_codes.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/discount_codes.json @@ -22,6 +22,15 @@ "type": ["null", "string"], "format": "date-time" }, + "summary": { + "type": ["null", "string"] + }, + "discount_type": { + "type": ["null", "string"] + }, + "admin_graphql_api_id": { + "type": ["null", "string"] + }, "shop_url": { "type": ["null", "string"] } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillment_orders.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillment_orders.json index 9d810f8a694a..d4644ee66075 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillment_orders.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillment_orders.json @@ -54,6 +54,14 @@ }, "method_type": { "type": ["null", "string"] + }, + "min_delivery_date_time": { + "type": ["null", "string"], + "format": "date-time" + }, + "max_delivery_date_time": { + "type": ["null", "string"], + "format": "date-time" } } }, @@ -99,7 +107,7 @@ "shop_id": { "type": ["null", "integer"] }, - "fullfillment_order_id": { + "fulfillment_order_id": { "type": ["null", "integer"] }, "line_item_id": { @@ -135,7 +143,15 @@ "supported_actions": { "type": ["null", "array"], "items": { - "type": ["null", "string"] + "type": ["null", "object"], + "properties": { + "action": { + "type": ["null", "string"] + }, + "external_url": { + "type": ["null", "string"] + } + } } }, "merchant_requests": { @@ -143,6 +159,9 @@ "items": { "type": ["null", "object"], "properties": { + "id": { + "type": ["null", "integer"] + }, "message": { "type": ["null", "string"] }, @@ -150,7 +169,13 @@ "type": ["null", "string"] }, "request_options": { - "type": ["null", "object"] + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "notify_customer": { + "type": ["null", "boolean"] + } + } } } } @@ -197,6 +222,9 @@ "updated_at": { "type": ["null", "string"], "format": "date-time" + }, + "admin_graphql_api_id": { + "type": ["null", "string"] } } } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillments.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillments.json index d04a0c3686c6..3b85a5fc97b2 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillments.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/fulfillments.json @@ -115,6 +115,33 @@ "price": { "type": ["null", "string"] }, + "price_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, "grams": { "type": ["null", "number"] }, @@ -163,6 +190,33 @@ "total_discount": { "type": ["null", "string"] }, + "total_discount_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, "fulfillment_status": { "type": ["null", "string"] }, @@ -174,9 +228,39 @@ "items": { "type": ["null", "object"], "properties": { + "channel_liable": { + "type": ["null", "boolean"] + }, "price": { "type": ["null", "number"] }, + "price_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, "rate": { "type": ["null", "number"] }, @@ -185,6 +269,149 @@ } } } + }, + "duties": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "harmonized_system_code": { + "type": ["null", "string"] + }, + "country_code_of_origin": { + "type": ["null", "string"] + }, + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "tax_lines": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "title": { + "type": ["null", "string"] + }, + "price": { + "type": ["null", "string"] + }, + "rate": { + "type": ["null", "number"] + }, + "price_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, + "channel_liable": { + "type": ["null", "boolean"] + } + } + } + } + } + } + }, + "discount_allocations": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "discount_application_index": { + "type": ["null", "number"] + }, + "amount_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "string"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, + "application_type": { + "type": ["null", "string"] + } + } + } + }, + "admin_graphql_api_id": { + "type": ["null", "string"] } } } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/order_refunds.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/order_refunds.json index aa1b05981036..85b2c167674f 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/order_refunds.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/order_refunds.json @@ -179,6 +179,9 @@ }, "rate": { "type": ["null", "number"] + }, + "channel_liable": { + "type": ["null", "boolean"] } }, "type": ["null", "object"] @@ -196,15 +199,7 @@ "properties": { "type": ["null", "array"], "items": { - "properties": { - "name": { - "type": ["null", "string"] - }, - "value": { - "type": ["null", "string"] - } - }, - "type": ["null", "object"] + "type": ["null", "string"] } }, "quantity": { @@ -379,6 +374,45 @@ }, "title": { "type": ["null", "string"] + }, + "duties": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "duty_id": { + "type": ["null", "integer"] + }, + "amount_set": { + "properties": { + "shop_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + }, + "presentment_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + } + }, + "type": ["null", "object"] + } + } + } } }, "type": ["null", "object"] @@ -473,6 +507,45 @@ }, "user_id": { "type": ["null", "integer"] + }, + "payment_details": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "avs_result_code": { + "type": ["null", "string"] + }, + "buyer_action_info": { + "type": ["null", "string"] + }, + "credit_card_bin": { + "type": ["null", "string"] + }, + "credit_card_company": { + "type": ["null", "string"] + }, + "credit_card_expiration_month": { + "type": ["null", "integer"] + }, + "credit_card_expiration_year": { + "type": ["null", "integer"] + }, + "credit_card_name": { + "type": ["null", "string"] + }, + "credit_card_number": { + "type": ["null", "string"] + }, + "credit_card_wallet": { + "type": ["null", "string"] + }, + "cvv_result_code": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] } } } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/orders.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/orders.json index 416b20b7d0f4..f7e975ac9e12 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/orders.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/orders.json @@ -447,6 +447,9 @@ "items": { "type": ["null", "object"], "properties": { + "channel_liable": { + "type": ["null", "boolean"] + }, "price": { "type": ["null", "number"] }, @@ -837,6 +840,50 @@ "type": ["null", "boolean"] } } + }, + "email_marketing_consent": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "state": { + "type": ["null", "string"] + }, + "opt_in_level": { + "type": ["null", "string"] + }, + "consent_updated_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "consent_collected_from": { + "type": ["null", "string"] + } + } + }, + "sms_marketing_consent": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "state": { + "type": ["null", "string"] + }, + "opt_in_level": { + "type": ["null", "string"] + }, + "consent_updated_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "consent_collected_from": { + "type": ["null", "string"] + } + } + }, + "tax_exemptions": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } } } }, @@ -1157,6 +1204,9 @@ "items": { "type": ["null", "object"], "properties": { + "channel_liable": { + "type": ["null", "boolean"] + }, "price": { "type": ["null", "number"] }, @@ -1341,6 +1391,30 @@ } } } + }, + "origin_address": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "address1": { + "type": ["null", "string"] + }, + "address2": { + "type": ["null", "string"] + }, + "city": { + "type": ["null", "string"] + }, + "country_code": { + "type": ["null", "string"] + }, + "province_code": { + "type": ["null", "string"] + }, + "zip": { + "type": ["null", "string"] + } + } } } } @@ -1547,6 +1621,9 @@ "items": { "type": ["null", "object"], "properties": { + "channel_liable": { + "type": ["null", "boolean"] + }, "price": { "type": ["null", "number"] }, @@ -1915,6 +1992,45 @@ }, "user_id": { "type": ["null", "integer"] + }, + "payment_details": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "avs_result_code": { + "type": ["null", "string"] + }, + "buyer_action_info": { + "type": ["null", "string"] + }, + "credit_card_bin": { + "type": ["null", "string"] + }, + "credit_card_company": { + "type": ["null", "string"] + }, + "credit_card_expiration_month": { + "type": ["null", "integer"] + }, + "credit_card_expiration_year": { + "type": ["null", "integer"] + }, + "credit_card_name": { + "type": ["null", "string"] + }, + "credit_card_number": { + "type": ["null", "string"] + }, + "credit_card_wallet": { + "type": ["null", "string"] + }, + "cvv_result_code": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] } } } @@ -2130,6 +2246,9 @@ "items": { "type": ["null", "object"], "properties": { + "channel_liable": { + "type": ["null", "boolean"] + }, "price": { "type": ["null", "string"] }, @@ -2209,11 +2328,116 @@ } } } + }, + "duties": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "duty_id": { + "type": ["null", "integer"] + }, + "amount_set": { + "properties": { + "shop_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + }, + "presentment_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + } + }, + "type": ["null", "object"] + } + } + } } } } } } + }, + "duties": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "duty_id": { + "type": ["null", "integer"] + }, + "amount_set": { + "properties": { + "shop_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + }, + "presentment_money": { + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + }, + "type": ["null", "object"] + } + }, + "type": ["null", "object"] + } + } + } + }, + "total_duties_set": { + "type": ["null", "object"], + "properties": { + "shop_money": { + "type": ["null", "object"], + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + } + }, + "presentment_money": { + "type": ["null", "object"], + "properties": { + "currency_code": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "number"] + } + } + } + } } } } diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/products.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/products.json index c97a60b74645..f70f3ecb39e7 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/products.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/products.json @@ -94,6 +94,9 @@ }, "width": { "type": ["null", "integer"] + }, + "product_id": { + "type": ["null", "integer"] } }, "type": ["null", "object"] @@ -139,6 +142,9 @@ }, "width": { "type": ["null", "integer"] + }, + "product_id": { + "type": ["null", "integer"] } }, "type": ["null", "object"] @@ -255,6 +261,9 @@ }, "option3": { "type": ["null", "string"] + }, + "product_id": { + "type": ["null", "integer"] } }, "type": ["null", "object"] diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/transactions.json b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/transactions.json index f8a05c8091f5..cec14d1d20b2 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/transactions.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/schemas/transactions.json @@ -57,6 +57,9 @@ }, "currency_code": { "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] } } }, @@ -68,6 +71,9 @@ }, "currency_code": { "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] } } } @@ -77,8 +83,13 @@ "type": ["null", "string"] }, "payment_details": { + "type": ["null", "object"], + "additionalProperties": true, "properties": { - "cvv_result_code": { + "avs_result_code": { + "type": ["null", "string"] + }, + "buyer_action_info": { "type": ["null", "string"] }, "credit_card_bin": { @@ -87,14 +98,25 @@ "credit_card_company": { "type": ["null", "string"] }, + "credit_card_expiration_month": { + "type": ["null", "integer"] + }, + "credit_card_expiration_year": { + "type": ["null", "integer"] + }, + "credit_card_name": { + "type": ["null", "string"] + }, "credit_card_number": { "type": ["null", "string"] }, - "avs_result_code": { + "credit_card_wallet": { + "type": ["null", "string"] + }, + "cvv_result_code": { "type": ["null", "string"] } - }, - "type": ["null", "object"] + } }, "processed_at": { "type": ["null", "string"], @@ -107,21 +129,29 @@ "type": ["null", "string"] }, "receipt": { - "type": ["null", "object"], - "properties": { - "fee_amount": { - "type": ["null", "number"], - "multipleOf": 1e-10 - }, - "gross_amount": { - "type": ["null", "number"], - "multipleOf": 1e-10 + "oneOf": [ + { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "fee_amount": { + "type": ["null", "number"], + "multipleOf": 1e-10 + }, + "gross_amount": { + "type": ["null", "number"], + "multipleOf": 1e-10 + }, + "tax_amount": { + "type": ["null", "number"], + "multipleOf": 1e-10 + } + } }, - "tax_amount": { - "type": ["null", "number"], - "multipleOf": 1e-10 + { + "type": ["null", "string"] } - } + ] }, "location_id": { "type": ["null", "integer"] diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/scopes.py b/airbyte-integrations/connectors/source-shopify/source_shopify/scopes.py new file mode 100644 index 000000000000..805acc1f8d68 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/scopes.py @@ -0,0 +1,157 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import logging +from typing import Any, Iterable, List, Mapping, Optional + +import requests +from requests.exceptions import ConnectionError, InvalidURL, JSONDecodeError, SSLError + +from .utils import ShopifyAccessScopesError, ShopifyBadJsonError, ShopifyConnectionError, ShopifyWrongShopNameError + +SCOPES_MAPPING: Mapping[str, set[str]] = { + # SCOPE: read_customers + "Customers": ("read_customers",), + "MetafieldCustomers": ("read_customers",), + "CustomerSavedSearch": ("read_customers",), + "CustomerAddress": ("read_customers",), + # SCOPE: read_orders + "Orders": ("read_orders",), + "AbandonedCheckouts": ("read_orders",), + "TenderTransactions": ("read_orders",), + "Transactions": ("read_orders",), + "TransactionsGraphql": ("read_orders",), + "Fulfillments": ("read_orders",), + "OrderRefunds": ("read_orders",), + "OrderRisks": ("read_orders",), + "MetafieldOrders": ("read_orders",), + # SCOPE: read_draft_orders + "DraftOrders": ("read_draft_orders",), + "MetafieldDraftOrders": ("read_draft_orders",), + # SCOPE: read_products + "Products": ("read_products",), + "ProductsGraphQl": ("read_products",), + "MetafieldProducts": ("read_products",), + "ProductImages": ("read_products",), + "MetafieldProductImages": ("read_products",), + "MetafieldProductVariants": ("read_products",), + "CustomCollections": ("read_products",), + "Collects": ("read_products",), + "ProductVariants": ("read_products",), + "MetafieldCollections": ("read_products",), + "SmartCollections": ("read_products",), + "MetafieldSmartCollections": ("read_products",), + # SCOPE: read_products, read_publications + "Collections": ("read_products", "read_publications"), + # SCOPE: read_content + "Pages": ("read_content",), + "MetafieldPages": ("read_content",), + # SCOPE: read_price_rules + "PriceRules": ("read_price_rules",), + # SCOPE: read_discounts + "DiscountCodes": ("read_discounts",), + # SCOPE: read_locations + "Locations": ("read_locations",), + "MetafieldLocations": ("read_locations",), + # SCOPE: read_inventory + "InventoryItems": ("read_inventory",), + "InventoryLevels": ("read_inventory",), + # SCOPE: read_merchant_managed_fulfillment_orders + "FulfillmentOrders": ("read_merchant_managed_fulfillment_orders",), + # SCOPE: read_shopify_payments_payouts + "BalanceTransactions": ("read_shopify_payments_payouts",), + "Disputes": ("read_shopify_payments_payouts",), + # SCOPE: read_online_store_pages + "Articles": ("read_online_store_pages",), + "MetafieldArticles": ("read_online_store_pages",), + "Blogs": ("read_online_store_pages",), + "MetafieldBlogs": ("read_online_store_pages",), +} + +ALWAYS_PERMITTED_STREAMS: List[str] = [ + "MetafieldShops", + "Shop", + "Countries", +] + + +class ShopifyScopes: + + # define default logger + logger = logging.getLogger("airbyte") + + def __init__(self, config: Mapping[str, Any]) -> None: + self.user_scopes = self.get_user_scopes(config) + # for each stream check the authenticated user has all scopes required + self.get_streams_from_user_scopes() + # log if there are streams missing scopes and should be omitted + self.emit_missing_scopes() + + # the list of validated streams + permitted_streams: List[str] = ALWAYS_PERMITTED_STREAMS + # the list of not permitted streams + not_permitted_streams: List[set[str, str]] = [] + # template for the log message + missing_scope_message: str = ( + "The stream `{stream}` could not be synced without the `{scope}` scope. Please check the `{scope}` is granted." + ) + + @staticmethod + def get_user_scopes(config) -> list[Any]: + session = requests.Session() + url = f"https://{config['shop']}.myshopify.com/admin/oauth/access_scopes.json" + headers = config["authenticator"].get_auth_header() + try: + response = session.get(url, headers=headers).json() + access_scopes = [scope.get("handle") for scope in response.get("access_scopes")] + except InvalidURL: + raise ShopifyWrongShopNameError(url) + except JSONDecodeError as json_error: + raise ShopifyBadJsonError(json_error) + except (SSLError, ConnectionError) as con_error: + raise ShopifyConnectionError(con_error) + + if access_scopes: + return access_scopes + else: + raise ShopifyAccessScopesError(response) + + def log_missing_scope(self, not_permitted_stream: Mapping[str, Any]) -> str: + stream_name, scope = not_permitted_stream + self.logger.warning(self.missing_scope_message.format(stream=stream_name, scope=scope)) + + def emit_missing_scopes(self) -> Optional[Iterable[List[str]]]: + if len(self.not_permitted_streams) > 0: + for not_permitted_stream in self.not_permitted_streams: + self.log_missing_scope(not_permitted_stream) + + def get_permitted_streams(self) -> List[str]: + # return the list of validated streams + return self.permitted_streams + + def not_permitted_streams_names(self) -> List[str]: + return [not_permitted[0] for not_permitted in self.not_permitted_streams] + + def stream_has_no_missing_scopes(self, stream_name: str) -> bool: + return stream_name not in self.not_permitted_streams_names() + + def check_user_has_stream_scope(self, stream_name: str, scope: str) -> None: + if scope not in self.user_scopes: + self.not_permitted_streams.append((stream_name, scope)) + + def register_permitted_stream(self, stream_name: str) -> None: + # allow stream only if there is a complete match with required scopes + if self.stream_has_no_missing_scopes(stream_name): + self.permitted_streams.append(stream_name) + + def validate_stream_scopes(self, stream_name: str, scopes_required: str) -> None: + for scope in scopes_required: + self.check_user_has_stream_scope(stream_name, scope) + + def get_streams_from_user_scopes(self) -> None: + # for each stream check the authenticated user has all scopes required + for stream_name, stream_scopes in SCOPES_MAPPING.items(): + self.validate_stream_scopes(stream_name, stream_scopes) + self.register_permitted_stream(stream_name) diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/exceptions.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/exceptions.py new file mode 100644 index 000000000000..51a0a0b004ff --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/exceptions.py @@ -0,0 +1,40 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +from airbyte_cdk.utils import AirbyteTracedException +from airbyte_protocol.models import FailureType + + +class ShopifyBulkExceptions: + class BaseBulkException(AirbyteTracedException): + def __init__(self, message: str, **kwargs) -> None: + super().__init__(internal_message=message, failure_type=FailureType.config_error, **kwargs) + + class BulkJobError(BaseBulkException): + """Raised when there are BULK Job Errors in response""" + + class BulkJobUnknownError(BaseBulkException): + """Raised when BULK Job has FAILED with Unknown status""" + + class BulkJobBadResponse(BaseBulkException): + """Raised when the requests.Response object could not be parsed""" + + class BulkJobResultUrlError(BaseBulkException): + """Raised when BULK Job has ACCESS_DENIED status""" + + class BulkRecordProduceError(BaseBulkException): + """Raised when there are error producing records from BULK Job result""" + + class BulkJobFailed(BaseBulkException): + """Raised when BULK Job has FAILED status""" + + class BulkJobTimout(BaseBulkException): + """Raised when BULK Job has TIMEOUT status""" + + class BulkJobAccessDenied(BaseBulkException): + """Raised when BULK Job has ACCESS_DENIED status""" + + class BulkJobConcurrentError(BaseBulkException): + """Raised when BULK Job could not be created, since the 1 Bulk job / shop quota is exceeded.""" diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/job.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/job.py new file mode 100644 index 000000000000..127b87161762 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/job.py @@ -0,0 +1,262 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +import logging +from dataclasses import dataclass, field +from enum import Enum +from time import sleep, time +from typing import Any, Iterable, List, Mapping, Optional, Union + +import requests +from airbyte_cdk import AirbyteLogger +from requests.exceptions import JSONDecodeError +from source_shopify.utils import ApiTypeEnum +from source_shopify.utils import ShopifyRateLimiter as limiter + +from .exceptions import AirbyteTracedException, ShopifyBulkExceptions +from .query import ShopifyBulkTemplates +from .tools import END_OF_FILE, BulkTools + + +class ShopifyBulkStatus(Enum): + CREATED = "CREATED" + COMPLETED = "COMPLETED" + RUNNING = "RUNNING" + FAILED = "FAILED" + TIMEOUT = "TIMEOUT" + ACCESS_DENIED = "ACCESS_DENIED" + + +@dataclass +class ShopifyBulkManager: + session: requests.Session + base_url: str + + # 5Mb chunk size to save the file + retrieve_chunk_size: int = 1024 * 1024 * 5 + # time between job status checks + job_check_interval_sec: int = 5 + + # PLATFORM HEARTBEAT NOTES: + # 30 sec / attempt * 19 attempts = 570 sec of wait time in total, + # which is < 10 min of retrying, before Heartbeat will kill the source as non-responsive + + # sleep time per creation attempt + concurrent_interval_sec = 30 + # max attempts for job creation + concurrent_max_retry: int = 19 + + # attempt limit indicator + concurrent_max_attempt_reached: bool = field(init=False, default=False) + # attempt counter + concurrent_attempt: int = field(init=False, default=0) + + # default logger + logger: AirbyteLogger = field(init=False, default=logging.getLogger("airbyte")) + + # currents: job_id, job_state + job_id: Optional[str] = field(init=False, default=None) + job_state: ShopifyBulkStatus = field(init=False, default=None) + + @property + def tools(self) -> BulkTools: + return BulkTools() + + @property + def job_state_to_fn_map(self) -> Mapping[str, Any]: + return { + ShopifyBulkStatus.CREATED.value: self.on_created_job, + ShopifyBulkStatus.COMPLETED.value: self.on_completed_job, + ShopifyBulkStatus.RUNNING.value: self.on_running_job, + ShopifyBulkStatus.TIMEOUT.value: self.on_timeout_job, + ShopifyBulkStatus.FAILED.value: self.on_failed_job, + ShopifyBulkStatus.ACCESS_DENIED.value: self.on_access_denied_job, + } + + def __reset_state(self) -> None: + # set current job state to default value + self.job_state, self.job_id = None, None + + def job_completed(self) -> bool: + return self.job_state == ShopifyBulkStatus.COMPLETED.value + + def log_state(self) -> None: + self.logger.info(f"The BULK Job: `{self.job_id}` is {self.job_state}.") + + def job_get_state_args(self) -> Mapping[str, Any]: + return { + "method": "POST", + "url": self.base_url, + "data": ShopifyBulkTemplates.status(self.job_id), + "headers": {"Content-Type": "application/graphql"}, + } + + def job_get_result(self, response: Optional[requests.Response] = None) -> Optional[str]: + job_result_url = response.json().get("data", {}).get("node", {}).get("url") if response else None + if job_result_url: + # save to local file using chunks to avoid OOM + filename = self.tools.filename_from_url(job_result_url) + with self.session.get(job_result_url, stream=True) as response: + response.raise_for_status() + with open(filename, "wb") as file: + for chunk in response.iter_content(chunk_size=self.retrieve_chunk_size): + file.write(chunk) + # add `` line to the bottom of the saved data for easy parsing + file.write(END_OF_FILE.encode()) + return filename + + def job_update_state(self, response: Optional[requests.Response] = None) -> None: + if response: + self.job_state = response.json().get("data", {}).get("node", {}).get("status") + self.log_state() + + def on_created_job(self, **kwargs) -> None: + pass + + def on_running_job(self, **kwargs) -> None: + sleep(self.job_check_interval_sec) + + def on_completed_job(self, **kwargs) -> None: + pass + + def on_failed_job(self, response: requests.Response) -> AirbyteTracedException: + raise ShopifyBulkExceptions.BulkJobFailed( + f"The BULK Job: `{self.job_id}` exited with {self.job_state}, details: {response.text}", + ) + + def on_timeout_job(self, **kwargs) -> AirbyteTracedException: + raise ShopifyBulkExceptions.BulkJobTimout( + f"The BULK Job: `{self.job_id}` exited with {self.job_state}, please reduce the `GraphQL BULK Date Range in Days` in SOURCES > Your Shopify Source > SETTINGS.", + ) + + def on_access_denied_job(self, **kwagrs) -> AirbyteTracedException: + raise ShopifyBulkExceptions.BulkJobAccessDenied( + f"The BULK Job: `{self.job_id}` exited with {self.job_state}, please check your PERMISSION to fetch the data for this stream.", + ) + + def on_job_with_errors(self, errors: List[Mapping[str, Any]]) -> AirbyteTracedException: + raise ShopifyBulkExceptions.BulkJobUnknownError(f"Could not validate the status of the BULK Job `{self.job_id}`. Errors: {errors}.") + + @limiter.balance_rate_limit(api_type=ApiTypeEnum.graphql.value) + def job_check_for_errors(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: + try: + return response.json().get("errors") or response.json().get("data", {}).get("bulkOperationRunQuery", {}).get("userErrors", []) + except (Exception, JSONDecodeError) as e: + raise ShopifyBulkExceptions.BulkJobBadResponse( + f"Couldn't check the `response` for `errors`, response: `{response.text}`. Trace: {repr(e)}." + ) + + def job_track_running(self) -> Union[AirbyteTracedException, requests.Response]: + # format Job state check args + status_args = self.job_get_state_args() + # re-use of `self._session(*, **)` to make BULK Job status checks + response = self.session.request(**status_args) + # errors check + errors = self.job_check_for_errors(response) + if not errors: + self.job_update_state(response) + self.job_state_to_fn_map.get(self.job_state)(response=response) + return response + else: + # execute ERRORS scenario + self.on_job_with_errors(errors) + + def job_check_state(self) -> Optional[str]: + while not self.job_completed(): + response = self.job_track_running() + # return `job_result_url` when status is `COMPLETED` + return self.job_get_result(response) + + def has_running_concurrent_job(self, errors: Optional[Iterable[Mapping[str, Any]]] = None) -> bool: + """ + When concurent BULK Job is already running for the same SHOP we receive: + Error example: + [ + { + 'field': None, + 'message': 'A bulk query operation for this app and shop is already in progress: gid://shopify/BulkOperation/4039184154813.', + } + ] + """ + + concurent_job_pattern = "A bulk query operation for this app and shop is already in progress" + # the errors are handled in `job_job_check_for_errors` + if errors: + for error in errors: + message = error.get("message", "") + if concurent_job_pattern in message: + return True + # reset the `concurrent_attempt` counter, once there is no concurrent job error + self.concurrent_attempt = 0 + return False + + def has_reached_max_concurrency_attempt(self) -> bool: + return self.concurrent_attempt == self.concurrent_max_retry + + def job_retry_concurrent(self, request: requests.PreparedRequest) -> Optional[requests.Response]: + # increment attempt + self.concurrent_attempt += 1 + # try to execute previous request, it's handy because we can retry / each slice yielded + self.logger.warning( + f"The BULK concurrency limit has reached. Waiting {self.concurrent_interval_sec} sec before retry, atttempt: {self.concurrent_attempt}.", + ) + sleep(self.concurrent_interval_sec) + # retry current `request` + return self.job_healthcheck(self.session.send(request)) + + def job_get_id(self, response: requests.Response) -> Optional[str]: + response_data = response.json() + bulk_response = response_data.get("data", {}).get("bulkOperationRunQuery", {}).get("bulkOperation", {}) + if bulk_response and bulk_response.get("status") == ShopifyBulkStatus.CREATED.value: + job_id = bulk_response.get("id") + self.logger.info(f"The BULK Job: `{job_id}` is {ShopifyBulkStatus.CREATED.value}") + return job_id + else: + return None + + def job_retry_on_concurrency(self, request: requests.PreparedRequest) -> Union[AirbyteTracedException, Optional[requests.Response]]: + if self.has_reached_max_concurrency_attempt(): + # indicate we're out of attempts to retry with job creation + message = f"The BULK Job couldn't be created at this time, since another job is running." + # log the message + self.logger.error(message) + # raise AibyteTracebackException with `INCOMPLETE` status + raise ShopifyBulkExceptions.BulkJobConcurrentError(message) + else: + return self.job_retry_concurrent(request) + + def job_healthcheck(self, response: requests.Response) -> Optional[requests.Response]: + # errors check + errors = self.job_check_for_errors(response) + # when the concurrent job takes place, we typically need to wait and retry, but no longer than 10 min. + if not self.has_running_concurrent_job(errors): + return response if not errors else None + else: + # get the latest request to retry + request: requests.PreparedRequest = response.request + return self.job_retry_on_concurrency(request) + + @limiter.balance_rate_limit(api_type=ApiTypeEnum.graphql.value) + def job_check(self, created_job_response: requests.Response) -> Optional[str]: + """ + This method checks the status for the BULK Job created, using it's `ID`. + The time spent for the Job execution is tracked to understand the effort. + """ + job_response = self.job_healthcheck(created_job_response) + self.job_id: str = self.job_get_id(job_response) + job_started = time() + try: + return self.job_check_state() + except ( + ShopifyBulkExceptions.BulkJobFailed, + ShopifyBulkExceptions.BulkJobTimout, + ShopifyBulkExceptions.BulkJobAccessDenied, + ShopifyBulkExceptions.BulkJobUnknownError, + ) as bulk_job_error: + raise bulk_job_error + finally: + time_elapsed = round((time() - job_started), 3) + self.logger.info(f"The BULK Job: `{self.job_id}` time elapsed: {time_elapsed} sec.") + # reset the state for COMPLETED job + self.__reset_state() diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/query.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/query.py new file mode 100644 index 000000000000..c614def08dfa --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/query.py @@ -0,0 +1,1484 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +from abc import abstractmethod +from dataclasses import dataclass +from enum import Enum +from string import Template +from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Union + +from attr import dataclass +from graphql_query import Argument, Field, InlineFragment, Operation, Query + +from .tools import BULK_PARENT_KEY, BulkTools + + +class ShopifyBulkTemplates: + @staticmethod + def status(bulk_job_id: str) -> str: + return Template( + """query { + node(id: "$job_id") { + ... on BulkOperation { + id + status + errorCode + objectCount + fileSize + url + partialDataUrl + } + } + }""" + ).substitute(job_id=bulk_job_id) + + @staticmethod + def prepare(query: str) -> str: + bulk_template = Template( + '''mutation { + bulkOperationRunQuery( + query: """ + $query + """ + ) { + bulkOperation { + id + status + } + userErrors { + field + message + } + } + }''' + ) + return bulk_template.substitute(query=query) + + +@dataclass +class ShopifyBulkQuery: + shop_id: int + + @property + def tools(self) -> BulkTools: + return BulkTools() + + @property + @abstractmethod + def query_name(self) -> str: + """ + Defines the root graph node name to fetch from: https://shopify.dev/docs/api/admin-graphql + """ + + @property + def record_composition(self) -> Optional[Mapping[str, Any]]: + """ + Example: + { + "new_record": "Collection", // the GQL Typename of the parent entity + "record_components": [ + "CollectionPublication" // each `collection` has List `publications` + ], + } + """ + return {} + + @property + def sort_key(self) -> Optional[str]: + """ + The field name by which the records are ASC sorted, if defined. + """ + return None + + @property + def query_nodes(self) -> Optional[Union[List[Field], List[str]]]: + """ + Defines the fields for final graph selection. + https://shopify.dev/docs/api/admin-graphql + """ + return ["__typename", "id"] + + def get(self, filter_field: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None) -> str: + # define filter query string, if passed + filter_query = f"{filter_field}:>='{start}' AND {filter_field}:<='{end}'" if filter_field else None + # building query + query: Query = self.query(filter_query) + # resolving + return self.resolve(query) + + def query(self, filter_query: Optional[str] = None) -> Query: + """ + Overide this method, if you need to customize query build logic. + Output example to BULK query `` with `filter query`: + { + (query: "") { + edges { + node { + id + } + } + } + } + """ + # return the constructed query operation + return self.build(self.query_name, self.query_nodes, filter_query) + + def build( + self, + name: str, + edges: Optional[Union[List[Field], List[InlineFragment], Field, InlineFragment]] = None, + filter_query: Optional[str] = None, + additional_query_args: Optional[Mapping[str, Any]] = None, + ) -> Query: + """ + Defines the root of the graph with edges. + """ + query_args: List[Argument] = [] + # constructing arguments + if filter_query: + query_args.append(Argument(name="query", value=f'"{filter_query}"')) + if self.sort_key: + query_args.append(Argument(name="sortKey", value=self.sort_key)) + if additional_query_args: + for k, v in additional_query_args.items(): + query_args.append(Argument(name=k, value=v)) + # constructing edges + query_fields = [ + Field(name="edges", fields=[Field(name="node", fields=edges if edges else ["id"])]), + ] + # return constucted query + return Query(name=name, arguments=query_args, fields=query_fields) + + def resolve(self, query: Query) -> str: + """ + Default query resolver from type(Operation) > type(str). + Overide this method to build multiple queries in one, if needed. + """ + # return the constructed query operation + return Operation(type="", queries=[query]).render() + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components, default `as is`. + """ + yield record + + +class MetafieldType(Enum): + CUSTOMERS = "customers" + ORDERS = "orders" + DRAFT_ORDERS = "draftOrders" + PRODUCTS = "products" + PRODUCT_IMAGES = ["products", "images"] + PRODUCT_VARIANTS = "productVariants" + COLLECTIONS = "collections" + LOCATIONS = "locations" + + +class Metafield(ShopifyBulkQuery): + """ + Only 2 lvl nesting is available: https://shopify.dev/docs/api/usage/bulk-operations/queries#operation-restrictions + Output example to BULK query `customers.metafields` with `filter query` by `updated_at` sorted `ASC`: + { + ( + query: "updated_at:>='2023-04-13' AND updated_at:<='2023-12-01'" + sortKey: UPDATED_AT + ) { + edges { + node { + __typename + id + metafields { + edges { + node { + __typename + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + sort_key = "UPDATED_AT" + record_composition = {"new_record": "Metafield"} + + metafield_fields: List[Field] = [ + "__typename", + "id", + "namespace", + "value", + "key", + "description", + "createdAt", + "updatedAt", + "type", + ] + + @property + def query_name(self) -> str: + if isinstance(self.type.value, list): + return self.type.value[0] + elif isinstance(self.type.value, str): + return self.type.value + + @property + @abstractmethod + def type(self) -> MetafieldType: + """ + Defines the Metafield type to fetch, see `MetafieldType` for more info. + """ + + def get_edge_node(self, name: str, fields: Union[List[str], List[Field], str]) -> Field: + """ + Defines the edge of the graph and it's fields to select for Shopify BULK Operaion. + https://shopify.dev/docs/api/usage/bulk-operations/queries#the-jsonl-data-format + """ + return Field(name=name, fields=[Field(name="edges", fields=[Field(name="node", fields=fields)])]) + + @property + def query_nodes(self) -> List[Field]: + """ + List of available fields: + https://shopify.dev/docs/api/admin-graphql/unstable/objects/Metafield + """ + # define metafield node + metafield_node = self.get_edge_node("metafields", self.metafield_fields) + + if isinstance(self.type.value, list): + return ["__typename", "id", self.get_edge_node(self.type.value[1], ["__typename", "id", metafield_node])] + elif isinstance(self.type.value, str): + return ["__typename", "id", metafield_node] + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + # resolve parent id from `str` to `int` + record["owner_id"] = self.tools.resolve_str_id(record.get(BULK_PARENT_KEY)) + # add `owner_resource` field + record["owner_resource"] = self.tools.camel_to_snake(record.get(BULK_PARENT_KEY, "").split("/")[3]) + # remove `__parentId` from record + record.pop(BULK_PARENT_KEY, None) + # convert dates from ISO-8601 to RFC-3339 + record["createdAt"] = self.tools.from_iso8601_to_rfc3339(record, "createdAt") + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + record = self.tools.fields_names_to_snake_case(record) + yield record + + +class MetafieldCollection(Metafield): + """ + { + collections(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + type = MetafieldType.COLLECTIONS + + +class MetafieldCustomer(Metafield): + """ + { + customers(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + type = MetafieldType.CUSTOMERS + + +class MetafieldLocation(Metafield): + """ + { + locations { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + sort_key = None + type = MetafieldType.LOCATIONS + + +class MetafieldOrder(Metafield): + """ + { + orders(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + type = MetafieldType.ORDERS + + +class MetafieldDraftOrder(Metafield): + """ + { + draftOrders(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + type = MetafieldType.DRAFT_ORDERS + + +class MetafieldProduct(Metafield): + """ + { + products(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + type = MetafieldType.PRODUCTS + + +class MetafieldProductImage(Metafield): + """ + { + products(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + id + images{ + edges{ + node{ + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + } + } + } + """ + + type = MetafieldType.PRODUCT_IMAGES + + +class MetafieldProductVariant(Metafield): + """ + { + productVariants(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'") { + edges { + node { + id + metafields { + edges { + node { + id + namespace + value + key + description + createdAt + updatedAt + type + } + } + } + } + } + } + } + """ + + sort_key = None + type = MetafieldType.PRODUCT_VARIANTS + + +class DiscountCode(ShopifyBulkQuery): + """ + Output example to BULK query `codeDiscountNodes` with `filter query` by `updated_at` sorted `ASC`: + { + codeDiscountNodes(query: "updated_at:>='2023-12-07T00:00:00Z' AND updated_at:<='2023-12-30T00:00:00Z'", sortKey: UPDATED_AT) { + edges { + node { + __typename + id + codeDiscount { + ... on DiscountCodeApp { + updatedAt + createdAt + discountType: discountClass + codes { + edges { + node { + __typename + usageCount: asyncUsageCount + code + id + } + } + } + } + ... on DiscountCodeBasic { + createdAt + updatedAt + discountType: discountClass + summary + codes { + edges { + node { + __typename + usageCount: asyncUsageCount + code + id + } + } + } + } + ... on DiscountCodeBxgy { + updatedAt + createdAt + discountType: discountClass + summary + codes { + edges { + node { + __typename + usageCount: asyncUsageCount + code + id + } + } + } + } + ... on DiscountCodeFreeShipping { + updatedAt + createdAt + discountType: discountClass + summary + codes { + edges { + node { + __typename + usageCount: asyncUsageCount + code + id + } + } + } + } + } + } + } + } + } + """ + + query_name = "codeDiscountNodes" + sort_key = "UPDATED_AT" + + code_discount_fields: List[Field] = [ + Field(name="discountClass", alias="discountType"), + Field( + name="codes", + fields=[ + Field( + name="edges", + fields=[ + Field( + name="node", + fields=[ + "__typename", + Field(name="asyncUsageCount", alias="usageCount"), + "code", + "id", + ], + ) + ], + ) + ], + ), + ] + + code_discount_fragments: List[InlineFragment] = [ + # the type: DiscountCodeApp has no `"summary"` field available + InlineFragment(type="DiscountCodeApp", fields=["updatedAt", "createdAt", *code_discount_fields]), + InlineFragment(type="DiscountCodeBasic", fields=["updatedAt", "createdAt", "summary", *code_discount_fields]), + InlineFragment(type="DiscountCodeBxgy", fields=["updatedAt", "createdAt", "summary", *code_discount_fields]), + InlineFragment(type="DiscountCodeFreeShipping", fields=["updatedAt", "createdAt", "summary", *code_discount_fields]), + ] + + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="codeDiscount", fields=code_discount_fragments), + ] + + record_composition = { + "new_record": "DiscountCodeNode", + # each DiscountCodeNode has `DiscountRedeemCode` + "record_components": ["DiscountRedeemCode"], + } + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components. + """ + + record_components = record.get("record_components", {}) + if record_components: + discounts = record_components.get("DiscountRedeemCode", []) + if len(discounts) > 0: + for discount in discounts: + # resolve parent id from `str` to `int` + discount["admin_graphql_api_id"] = discount.get("id") + discount["price_rule_id"] = self.tools.resolve_str_id(discount.get(BULK_PARENT_KEY)) + discount["id"] = self.tools.resolve_str_id(discount.get("id")) + code_discount = record.get("codeDiscount", {}) + if code_discount: + discount.update(**code_discount) + discount.pop(BULK_PARENT_KEY, None) + # field names to snake case for discount + discount = self.tools.fields_names_to_snake_case(discount) + # convert dates from ISO-8601 to RFC-3339 + discount["created_at"] = self.tools.from_iso8601_to_rfc3339(discount, "created_at") + discount["updated_at"] = self.tools.from_iso8601_to_rfc3339(discount, "updated_at") + yield discount + + +class Collection(ShopifyBulkQuery): + """ + { + collections(query: "updated_at:>='2023-02-07T00:00:00+00:00' AND updated_at:<='2023-12-04T00:00:00+00:00'", sortKey: UPDATED_AT) { + edges { + node { + __typename + id + handle + title + updatedAt + bodyHtml: descriptionHtml + publications { + edges { + node { + __typename + publishedAt: publishDate + } + } + } + sortOrder + templateSuffix + productsCount + } + } + } + } + """ + + query_name = "collections" + sort_key = "UPDATED_AT" + + publications_fields: List[Field] = [ + Field(name="edges", fields=[Field(name="node", fields=["__typename", Field(name="publishDate", alias="publishedAt")])]) + ] + + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="handle"), + Field(name="title"), + Field(name="updatedAt"), + Field(name="descriptionHtml", alias="bodyHtml"), + Field(name="publications", fields=publications_fields), + Field(name="sortOrder"), + Field(name="templateSuffix"), + Field(name="productsCount"), + ] + + record_composition = { + "new_record": "Collection", + # each collection has `publications` + "record_components": ["CollectionPublication"], + } + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components. + """ + record_components = record.get("record_components", {}) + if record_components: + publications = record_components.get("CollectionPublication", []) + if len(publications) > 0: + record["published_at"] = publications[0].get("publishedAt") + record.pop("record_components") + # convert dates from ISO-8601 to RFC-3339 + record["published_at"] = self.tools.from_iso8601_to_rfc3339(record, "published_at") + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + # remove leftovers + record.pop(BULK_PARENT_KEY, None) + yield record + + +class CustomerAddresses(ShopifyBulkQuery): + """ + { + customers(query: "updated_at:>='2024-01-20T00:00:00+00:00' AND updated_at:<'2024-01-24T00:00:00+00:00'", sortKey:UPDATED_AT) { + edges { + node { + __typename + customerId: id + defaultAddress { + id + } + addresses { + address1 + address2 + city + country + countryCode + company + firstName + id + lastName + name + phone + province + provinceCode + zip + } + } + } + } + } + """ + + query_name = "customers" + sort_key = "UPDATED_AT" + + addresses_fields: List[str] = [ + "address1", + "address2", + "city", + "country", + "countryCode", + "company", + "firstName", + "id", + "lastName", + "name", + "phone", + "province", + "provinceCode", + "zip", + ] + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="defaultAddress", fields=["id"]), + Field(name="addresses", fields=addresses_fields), + # add `Customer.updated_at` field to provide the parent state + "updatedAt", + ] + + record_composition = { + "new_record": "Customer", + } + + def set_default_address(self, record: MutableMapping[str, Any], address_record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + default_address = record.get("defaultAddress", {}) + # the default_address could be literal `None`, additional check is required + if default_address: + if address_record.get("id") == record.get("defaultAddress", {}).get("id"): + address_record["default"] = True + return address_record + + def record_process_components(self, record: MutableMapping[str, Any]) -> Optional[Iterable[MutableMapping[str, Any]]]: + """ + Defines how to process collected components. + """ + if "addresses" in record.keys(): + addresses = record.get("addresses") + if len(addresses) > 0: + for customer_address in addresses: + # add `customer_id` to each address entry + customer_address["customer_id"] = record.get("id") + # add `country_name` from `country` + customer_address["country_name"] = customer_address.get("country") + # default address check + customer_address = self.set_default_address(record, customer_address) + # resolve address id + customer_address["id"] = self.tools.resolve_str_id(customer_address.get("id")) + # add PARENT stream cursor_field to the root level of the record + # providing the ability to track the PARENT state as well + # convert dates from ISO-8601 to RFC-3339 + customer_address["updated_at"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + # names to snake + customer_address = self.tools.fields_names_to_snake_case(customer_address) + yield customer_address + + +class InventoryItem(ShopifyBulkQuery): + """ + { + inventoryItems(query: "updated_at:>='2022-04-13T00:00:00+00:00' AND updated_at:<='2023-02-07T00:00:00+00:00'") { + edges { + node { + __typename + unitCost { + cost: amount + } + countryCodeOfOrigin + countryHarmonizedSystemCodes { + edges { + node { + harmonizedSystemCode + countryCode + } + } + } + harmonizedSystemCode + provinceCodeOfOrigin + updatedAt + createdAt + sku + tracked + requiresShipping + } + } + } + } + """ + + query_name = "inventoryItems" + + country_harmonizedS_system_codes: List[Field] = [ + Field(name="edges", fields=[Field(name="node", fields=["__typename", "harmonizedSystemCode", "countryCode"])]) + ] + + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="unitCost", fields=[Field(name="amount", alias="cost")]), + Field(name="countryCodeOfOrigin"), + Field(name="countryHarmonizedSystemCodes", fields=country_harmonizedS_system_codes), + Field(name="harmonizedSystemCode"), + Field(name="provinceCodeOfOrigin"), + Field(name="updatedAt"), + Field(name="createdAt"), + Field(name="sku"), + Field(name="tracked"), + Field(name="requiresShipping"), + ] + + record_composition = { + "new_record": "InventoryItem", + } + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components. + """ + + # resolve `cost` to root lvl as `number` + unit_cost = record.get("unitCost", {}) + if unit_cost: + record["cost"] = float(unit_cost.get("cost")) + else: + record["cost"] = None + # clean up + record.pop("unitCost", None) + # add empty `country_harmonized_system_codes` array, if missing for record + if "countryHarmonizedSystemCodes" not in record.keys(): + record["country_harmonized_system_codes"] = [] + # convert dates from ISO-8601 to RFC-3339 + record["createdAt"] = self.tools.from_iso8601_to_rfc3339(record, "createdAt") + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + record = self.tools.fields_names_to_snake_case(record) + yield record + + +class InventoryLevel(ShopifyBulkQuery): + """ + Output example to BULK query `inventory_levels` from `locations` with `filter query` by `updated_at`: + { + locations(includeLegacy: true, includeInactive: true) { + edges { + node { + __typename + id + inventoryLevels(query: "updated_at:>='2023-04-14T00:00:00+00:00'") { + edges { + node { + __typename + id + available + item { + inventory_item_id: id + } + updatedAt + } + } + } + } + } + } + } + """ + + query_name = "locations" + # in order to return all the locations, additional query args must be provided + # https://shopify.dev/docs/api/admin-graphql/2023-10/queries/locations#query-arguments + locations_query_args = { + "includeLegacy": "true", + "includeInactive": "true", + } + record_composition = { + "new_record": "InventoryLevel", + } + + inventory_levels_fields: List[Field] = [ + "__typename", + "id", + Field(name="available"), + Field(name="item", fields=[Field(name="id", alias="inventory_item_id")]), + Field(name="updatedAt"), + ] + + def query(self, filter_query: Optional[str] = None) -> Query: + # build the nested query first with `filter_query` to have the incremental syncs + inventory_levels: List[Query] = [self.build("inventoryLevels", self.inventory_levels_fields, filter_query)] + # build the main query around previous + # return the constructed query operation + return self.build( + name=self.query_name, + edges=self.query_nodes + inventory_levels, + # passing more query args for `locations` query + additional_query_args=self.locations_query_args, + ) + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components. + """ + + # resolve `inventory_item_id` to root lvl + resolve to int + record["inventory_item_id"] = self.tools.resolve_str_id(record.get("item", {}).get("inventory_item_id")) + # add `location_id` from `__parentId` + record["location_id"] = self.tools.resolve_str_id(record[BULK_PARENT_KEY]) + # make composite `id` from `location_id|inventory_item_id` + record["id"] = "|".join((str(record.get("location_id", "")), str(record.get("inventory_item_id", "")))) + # convert dates from ISO-8601 to RFC-3339 + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + # remove leftovers + record.pop("item", None) + record.pop(BULK_PARENT_KEY, None) + record = self.tools.fields_names_to_snake_case(record) + yield record + + +class FulfillmentOrder(ShopifyBulkQuery): + """ + Output example to BULK query `fulfillmentOrders` from `orders` with `filter query` by `updated_at`, sorted by `UPDATED_AT`: + { + orders(query: "updated_at:>='2023-04-13T05:00:09Z' and updated_at:<='2023-04-15T05:00:09Z'", sortKey: UPDATED_AT){ + edges { + node { + __typename + id + fulfillmentOrders { + edges { + node { + __typename + id + assignedLocation { + location { + locationId: id + } + address1 + address2 + city + countryCode + name + phone + province + zip + } + destination { + id + address1 + address2 + city + company + countryCode + email + firstName + lastName + phone + province + zip + } + deliveryMethod { + id + methodType + minDeliveryDateTime + maxDeliveryDateTime + } + fulfillAt + fulfillBy + internationalDuties { + incoterm + } + fulfillmentHolds { + reason + reasonNotes + } + lineItems { + edges { + node { + __typename + id + inventoryItemId + lineItem { + lineItemId: id + fulfillableQuantity + quantity: currentQuantity + variant { + variantId: id + } + } + } + } + } + createdAt + updatedAt + requestStatus + status + supportedActions { + action + externalUrl + } + merchantRequests { + edges { + node { + __typename + id + message + kind + requestOptions + } + } + } + } + } + } + } + } + } + } + """ + + query_name = "orders" + sort_key = "UPDATED_AT" + + assigned_location_fields: List[Field] = [ + "address1", + "address2", + "city", + "countryCode", + "name", + "phone", + "province", + "zip", + Field(name="location", fields=[Field(name="id", alias="locationId")]), + ] + + destination_fields: List[Field] = [ + "id", + "address1", + "address2", + "city", + "company", + "countryCode", + "email", + "firstName", + "lastName", + "phone", + "province", + "zip", + ] + + delivery_method_fields: List[Field] = [ + "id", + "methodType", + "minDeliveryDateTime", + "maxDeliveryDateTime", + ] + + line_items_fields: List[Field] = [ + "__typename", + "id", + "inventoryItemId", + Field( + name="lineItem", + fields=[ + Field(name="id", alias="lineItemId"), + "fulfillableQuantity", + Field(name="currentQuantity", alias="quantity"), + Field(name="variant", fields=[Field(name="id", alias="variantId")]), + ], + ), + ] + + merchant_requests_fields: List[Field] = [ + "__typename", + "id", + "message", + "kind", + "requestOptions", + ] + + fulfillment_order_fields: List[Field] = [ + "__typename", + "id", + Field(name="assignedLocation", fields=assigned_location_fields), + Field(name="destination", fields=destination_fields), + Field(name="deliveryMethod", fields=delivery_method_fields), + "fulfillAt", + "fulfillBy", + Field(name="internationalDuties", fields=["incoterm"]), + Field(name="fulfillmentHolds", fields=["reason", "reasonNotes"]), + Field(name="lineItems", fields=[Field(name="edges", fields=[Field(name="node", fields=line_items_fields)])]), + "createdAt", + "updatedAt", + "requestStatus", + "status", + Field(name="supportedActions", fields=["action", "externalUrl"]), + Field(name="merchantRequests", fields=[Field(name="edges", fields=[Field(name="node", fields=merchant_requests_fields)])]), + ] + + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="fulfillmentOrders", fields=[Field(name="edges", fields=[Field(name="node", fields=fulfillment_order_fields)])]), + ] + + record_composition = { + "new_record": "FulfillmentOrder", + # each FulfillmentOrder has multiple `FulfillmentOrderLineItem` and `FulfillmentOrderMerchantRequest` + "record_components": [ + "FulfillmentOrderLineItem", + "FulfillmentOrderMerchantRequest", + ], + } + + def process_fulfillment_order(self, record: MutableMapping[str, Any], shop_id: int) -> MutableMapping[str, Any]: + # addings + record["shop_id"] = shop_id + record["order_id"] = record.get(BULK_PARENT_KEY) + # unnest nested locationId to the `assignedLocation` + location_id = record.get("assignedLocation", {}).get("location", {}).get("locationId") + record["assignedLocation"]["locationId"] = location_id + record["assigned_location_id"] = location_id + # create nested placeholders for other parts + record["line_items"] = [] + record["merchant_requests"] = [] + # cleaning + record.pop(BULK_PARENT_KEY) + record.get("assignedLocation").pop("location", None) + # resolve ids from `str` to `int` + # location id + location = record.get("assignedLocation", {}) + if location: + location_id = location.get("locationId") + if location_id: + record["assignedLocation"]["locationId"] = self.tools.resolve_str_id(location_id) + # assigned_location_id + record["assigned_location_id"] = self.tools.resolve_str_id(record.get("assigned_location_id")) + # destination id + destination = record.get("destination", {}) + if destination: + destination_id = destination.get("id") + if destination_id: + record["destination"]["id"] = self.tools.resolve_str_id(destination_id) + # delivery method id + delivery_method = record.get("deliveryMethod", {}) + if delivery_method: + delivery_method_id = delivery_method.get("id") + if delivery_method_id: + record["deliveryMethod"]["id"] = self.tools.resolve_str_id(delivery_method_id) + # order id + record["order_id"] = self.tools.resolve_str_id(record.get("order_id")) + # field names to snake for nested objects + # `assignedLocation`(object) field names to snake case + record["assignedLocation"] = self.tools.fields_names_to_snake_case(record.get("assignedLocation")) + # `deliveryMethod`(object) field names to snake case + record["deliveryMethod"] = self.tools.fields_names_to_snake_case(record.get("deliveryMethod")) + # `destination`(object) field names to snake case + record["destination"] = self.tools.fields_names_to_snake_case(record.get("destination")) + # `fulfillmentHolds`(list[object]) field names to snake case + record["fulfillment_holds"] = [self.tools.fields_names_to_snake_case(el) for el in record.get("fulfillment_holds", [])] + # `supportedActions`(list[object]) field names to snake case + record["supported_actions"] = [self.tools.fields_names_to_snake_case(el) for el in record.get("supported_actions", [])] + return record + + def process_line_item(self, record: MutableMapping[str, Any], shop_id: int) -> MutableMapping[str, Any]: + # addings + record["shop_id"] = shop_id + record["fulfillmentOrderId"] = record.get(BULK_PARENT_KEY) + # unnesting nested `lineItem` + line_item = record.get("lineItem", {}) + if line_item: + record["quantity"] = line_item.get("quantity") + record["lineItemId"] = line_item.get("lineItemId") + record["fulfillableQuantity"] = line_item.get("fulfillableQuantity") + variant = line_item.get("variant", {}) + if variant: + record["variantId"] = variant.get("variantId") + # cleaning + record.pop(BULK_PARENT_KEY) + record.pop("lineItem") + # resolve ids from `str` to `int` + record["id"] = self.tools.resolve_str_id(record.get("id")) + # inventoryItemId + record["inventoryItemId"] = self.tools.resolve_str_id(record.get("inventoryItemId")) + # fulfillmentOrderId + record["fulfillmentOrderId"] = self.tools.resolve_str_id(record.get("fulfillmentOrderId")) + # lineItemId + record["lineItemId"] = self.tools.resolve_str_id(record.get("lineItemId")) + # variantId + record["variantId"] = self.tools.resolve_str_id(record.get("variantId")) + # field names to snake case + record = self.tools.fields_names_to_snake_case(record) + return record + + def process_merchant_request(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + # cleaning + record.pop(BULK_PARENT_KEY) + # resolve ids from `str` to `int` + record["id"] = self.tools.resolve_str_id(record.get("id")) + # field names to snake case + record = self.tools.fields_names_to_snake_case(record) + return record + + def record_process_components(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + Defines how to process collected components. + """ + + record = self.process_fulfillment_order(record, self.shop_id) + record_components = record.get("record_components", {}) + if record_components: + line_items = record_components.get("FulfillmentOrderLineItem", []) + if len(line_items) > 0: + for line_item in line_items: + record["line_items"].append(self.process_line_item(line_item, self.shop_id)) + merchant_requests = record_components.get("FulfillmentOrderMerchantRequest", []) + if len(merchant_requests) > 0: + for merchant_request in merchant_requests: + record["merchant_requests"].append(self.process_merchant_request(merchant_request)) + record.pop("record_components") + # convert dates from ISO-8601 to RFC-3339 + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + # convert dates from ISO-8601 to RFC-3339 + record["fulfillAt"] = self.tools.from_iso8601_to_rfc3339(record, "fulfillAt") + record["createdAt"] = self.tools.from_iso8601_to_rfc3339(record, "createdAt") + record["updatedAt"] = self.tools.from_iso8601_to_rfc3339(record, "updatedAt") + # delivery method + delivery_method = record.get("deliveryMethod", {}) + if delivery_method: + record["deliveryMethod"]["min_delivery_date_time"] = self.tools.from_iso8601_to_rfc3339( + delivery_method, "min_delivery_date_time" + ) + record["deliveryMethod"]["max_delivery_date_time"] = self.tools.from_iso8601_to_rfc3339( + delivery_method, "max_delivery_date_time" + ) + yield record + + +class Transaction(ShopifyBulkQuery): + """ + Output example to BULK query `transactions` from `orders` with `filter query` by `updated_at` sorted `ASC`: + { + orders(query: "updated_at:>='2021-05-23T00:00:00+00:00' AND updated_at:<'2021-12-22T00:00:00+00:00'", sortKey:UPDATED_AT) { + edges { + node { + __typename + id + currency: currencyCode + transactions { + id + errorCode + parentTransaction { + parentId: id + } + test + kind + amount + receipt: receiptJson + gateway + authorization: authorizationCode + createdAt + status + processedAt + totalUnsettledSet { + presentmentMoney { + amount + currency: currencyCode + } + shopMoney { + amount + currency: currencyCode + } + } + paymentId + paymentDetails { + ... on CardPaymentDetails { + avsResultCode + creditCardBin: bin + creditCardCompany: company + creditCardNumber: number + creditCardName: name + cvvResultCode + creditCardWallet: wallet + creditCardExpirationYear: expirationYear + creditCardExpirationMonth: expirationMonth + } + } + } + } + } + } + } + """ + + query_name = "orders" + sort_key = "UPDATED_AT" + + total_unsettled_set_fields: List[Field] = [ + Field(name="presentmentMoney", fields=["amount", Field(name="currencyCode", alias="currency")]), + Field(name="shopMoney", fields=["amount", Field(name="currencyCode", alias="currency")]), + ] + + payment_details: List[InlineFragment] = [ + InlineFragment( + type="CardPaymentDetails", + fields=[ + "avsResultCode", + "cvvResultCode", + Field(name="bin", alias="creditCardBin"), + Field(name="company", alias="creditCardCompany"), + Field(name="number", alias="creditCardNumber"), + Field(name="name", alias="creditCardName"), + Field(name="wallet", alias="creditCardWallet"), + Field(name="expirationYear", alias="creditCardExpirationYear"), + Field(name="expirationMonth", alias="creditCardExpirationMonth"), + ], + ) + ] + + query_nodes: List[Field] = [ + "__typename", + "id", + Field(name="currencyCode", alias="currency"), + Field( + name="transactions", + fields=[ + "id", + "errorCode", + Field(name="parentTransaction", fields=[Field(name="id", alias="parentId")]), + "test", + "kind", + "amount", + Field(name="receiptJson", alias="receipt"), + "gateway", + Field(name="authorizationCode", alias="authorization"), + "createdAt", + "status", + "processedAt", + Field(name="totalUnsettledSet", fields=total_unsettled_set_fields), + "paymentId", + Field(name="paymentDetails", fields=payment_details), + ], + ), + ] + + record_composition = { + "new_record": "Order", + } + + def process_transaction(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + # save the id before it's resolved + record["admin_graphql_api_id"] = record.get("id") + # unnest nested fields + parent_transaction = record.get("parentTransaction", {}) + if parent_transaction: + record["parent_id"] = parent_transaction.get("parentId") + # str values to float + record["amount"] = float(record.get("amount")) + # convert dates from ISO-8601 to RFC-3339 + record["processedAt"] = self.tools.from_iso8601_to_rfc3339(record, "processedAt") + record["createdAt"] = self.tools.from_iso8601_to_rfc3339(record, "createdAt") + # resolve ids + record["id"] = self.tools.resolve_str_id(record.get("id")) + record["parent_id"] = self.tools.resolve_str_id(record.get("parent_id")) + # remove leftovers + record.pop("parentTransaction", None) + # field names to snake case + total_unsettled_set = record.get("totalUnsettledSet", {}) + if total_unsettled_set: + record["totalUnsettledSet"] = self.tools.fields_names_to_snake_case(total_unsettled_set) + # nested str values to float + record["totalUnsettledSet"]["presentment_money"]["amount"] = float( + total_unsettled_set.get("presentmentMoney", {}).get("amount") + ) + record["totalUnsettledSet"]["shop_money"]["amount"] = float(total_unsettled_set.get("shopMoney", {}).get("amount")) + payment_details = record.get("paymentDetails", {}) + if payment_details: + record["paymentDetails"] = self.tools.fields_names_to_snake_case(payment_details) + # field names to snake case for root level + record = self.tools.fields_names_to_snake_case(record) + return record + + def record_process_components(self, record: MutableMapping[str, Any]) -> Optional[MutableMapping[str, Any]]: + """ + Defines how to process collected components. + """ + + if "transactions" in record.keys(): + transactions = record.get("transactions") + if len(transactions) > 0: + for transaction in transactions: + # populate parent record keys + transaction["order_id"] = record.get("id") + transaction["currency"] = record.get("currency") + yield self.process_transaction(transaction) diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/record.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/record.py new file mode 100644 index 000000000000..5564dad60822 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/record.py @@ -0,0 +1,154 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import logging +from dataclasses import dataclass, field +from io import TextIOWrapper +from json import loads +from os import remove +from typing import Any, Callable, Iterable, List, Mapping, MutableMapping, Optional, Union + +from airbyte_cdk import AirbyteLogger + +from .exceptions import ShopifyBulkExceptions +from .query import ShopifyBulkQuery +from .tools import END_OF_FILE, BulkTools + + +@dataclass +class ShopifyBulkRecord: + query: ShopifyBulkQuery + + # default buffer + buffer: List[MutableMapping[str, Any]] = field(init=False, default_factory=list) + + # default logger + logger: AirbyteLogger = field(init=False, default=logging.getLogger("airbyte")) + + def __post_init__(self) -> None: + self.composition: Optional[Mapping[str, Any]] = self.query.record_composition + self.record_process_components: Optional[Callable[[MutableMapping], MutableMapping]] = self.query.record_process_components + self.components: List[str] = self.composition.get("record_components", []) if self.composition else [] + + @property + def tools(self) -> BulkTools: + return BulkTools() + + @staticmethod + def check_type(record: Mapping[str, Any], types: Union[List[str], str]) -> bool: + record_type = record.get("__typename") + if isinstance(types, list): + return any(record_type == t for t in types) + else: + return record_type == types + + def record_new(self, record: MutableMapping[str, Any]) -> None: + record = self.component_prepare(record) + record.pop("__typename") + self.buffer.append(record) + + def record_new_component(self, record: MutableMapping[str, Any]) -> None: + component = record.get("__typename") + record.pop("__typename") + # add component to its placeholder in the components list + self.buffer[-1]["record_components"][component].append(record) + + def component_prepare(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + if self.components: + record["record_components"] = {} + for component in self.components: + record["record_components"][component] = [] + return record + + def buffer_flush(self) -> Iterable[Mapping[str, Any]]: + if len(self.buffer) > 0: + for record in self.buffer: + # resolve id from `str` to `int` + record = self.record_resolve_id(record) + # process record components + yield from self.record_process_components(record) + # clean the buffer + self.buffer.clear() + + def record_compose(self, record: Mapping[str, Any]) -> Optional[Iterable[MutableMapping[str, Any]]]: + """ + Step 1: register the new record by it's `__typename` + Step 2: check for `components` by their `__typename` and add to the placeholder + Step 3: repeat until the ``. + """ + if self.check_type(record, self.composition.get("new_record")): + # emit from previous iteration, if present + yield from self.buffer_flush() + # register the record + self.record_new(record) + # components check + elif self.check_type(record, self.components): + self.record_new_component(record) + + def process_line(self, jsonl_file: TextIOWrapper) -> Iterable[MutableMapping[str, Any]]: + # process the json lines + for line in jsonl_file: + # we exit from the loop when receive (file ends) + if line == END_OF_FILE: + break + elif line != "": + yield from self.record_compose(loads(line)) + + # emit what's left in the buffer, typically last record + yield from self.buffer_flush() + + def record_resolve_id(self, record: MutableMapping[str, Any]) -> MutableMapping[str, Any]: + """ + The ids are fetched in the format of: " gid://shopify/Order/ " + Input: + { "Id": "gid://shopify/Order/19435458986123"} + We need to extract the actual id from the string instead. + Output: + { "id": 19435458986123, "admin_graphql_api_id": "gid://shopify/Order/19435458986123"} + """ + # save the actual api id to the `admin_graphql_api_id` + # while resolving the `id` in `record_resolve_id`, + # we re-assign the original id like `"gid://shopify/Order/19435458986123"`, + # into `admin_graphql_api_id` have the ability to identify the record oigin correctly in subsequent actions. + id = record.get("id") + if isinstance(id, str): + record["admin_graphql_api_id"] = id + # extracting the int(id) and reassign + record["id"] = self.tools.resolve_str_id(id) + return record + elif isinstance(id, int): + return record + + def produce_records(self, filename: str) -> Iterable[MutableMapping[str, Any]]: + """ + Read the JSONL content saved from `job.job_retrieve_result()` line-by-line to avoid OOM. + The filename example: `bulk-4039263649981.jsonl`, + where `4039263649981` is the `id` of the COMPLETED BULK Jobw with `result_url`. + Note: typically the `filename` is taken from the `result_url` string provided in the response. + """ + + with open(filename, "r") as jsonl_file: + for record in self.process_line(jsonl_file): + yield self.tools.fields_names_to_snake_case(record) + + def read_file(self, filename: str, remove_file: Optional[bool] = True) -> Iterable[Mapping[str, Any]]: + try: + # produce records from saved result + yield from self.produce_records(filename) + except Exception as e: + raise ShopifyBulkExceptions.BulkRecordProduceError( + f"An error occured while producing records from BULK Job result. Trace: {repr(e)}.", + ) + finally: + # removing the tmp file, if requested + if remove_file and filename: + try: + remove(filename) + except Exception as e: + self.logger.info(f"Failed to remove the `tmp job result` file, the file doen't exist. Details: {repr(e)}.") + # we should pass here, if the file wasn't removed , it's either: + # - doesn't exist + # - will be dropped with the container shut down. + pass diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/tools.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/tools.py new file mode 100644 index 000000000000..bd5d26099edb --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/bulk/tools.py @@ -0,0 +1,83 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import re +from typing import Any, Mapping, MutableMapping, Optional, Union +from urllib.parse import parse_qsl, urlparse + +import pendulum as pdm + +from .exceptions import ShopifyBulkExceptions + +# default end line tag +END_OF_FILE: str = "" +BULK_PARENT_KEY: str = "__parentId" + + +class BulkTools: + @staticmethod + def camel_to_snake(camel_case: str) -> str: + snake_case = [] + for char in camel_case: + if char.isupper(): + snake_case.append("_" + char.lower()) + else: + snake_case.append(char) + return "".join(snake_case).lstrip("_") + + @staticmethod + def filename_from_url(job_result_url: str) -> str: + """ + Example of `job_result_url` (str) : + https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/? + GoogleAccessId=assets-us-prod%40shopify-tiers.iam.gserviceaccount.com& + Expires=1705508208& + Signature=%3D%3D& + response-content-disposition=attachment%3B+filename%3D%22bulk-4147374162109.jsonl%22%3B+filename%2A%3DUTF-8%27%27bulk-4147374162109.jsonl& + response-content-type=application%2Fjsonl + + Output: + (str): bulk-4147374162109.jsonl + """ + # Regular expression pattern to extract the filename + filename_pattern = r'filename\*?=(?:UTF-8\'\')?"([^"]+)"' + parsed_url = dict(parse_qsl(urlparse(job_result_url).query)) + match = re.search(filename_pattern, parsed_url.get("response-content-disposition", "")) + if match: + return match.group(1) + else: + raise ShopifyBulkExceptions.BulkJobResultUrlError( + f"Could not extract the `filename` from `result_url` provided, details: {job_result_url}", + ) + + @staticmethod + def from_iso8601_to_rfc3339(record: Mapping[str, Any], field: str) -> Mapping[str, Any]: + """ + Converts date-time as follows: + Input: "2023-01-01T15:00:00Z" + Output: "2023-01-01T15:00:00+00:00" + If the value of the `field` is `None` we return it `as is`. + """ + # some fields that expected to be resolved as ids, might not be populated for the particular `RECORD`, + # we should return `None` to make the field `null` in the output as the result of the transformation. + target_value = record.get(field) + return pdm.parse(target_value).to_rfc3339_string() if target_value else record.get(field) + + def fields_names_to_snake_case(self, dict_input: Optional[Mapping[str, Any]] = None) -> Optional[MutableMapping[str, Any]]: + # transforming record field names from camel to snake case, leaving the `__parent_id` relation in place + if dict_input: + # the `None` type check is required, to properly handle nested missing entities (return None) + return {self.camel_to_snake(k) if dict_input and k != BULK_PARENT_KEY else k: v for k, v in dict_input.items()} + + @staticmethod + def resolve_str_id( + str_input: Optional[str] = None, output_type: Optional[Union[int, str, float]] = int + ) -> Optional[Union[int, str, float]]: + # some fields that expected to be resolved as ids, might not be populated for the particular `RECORD`, + # we should return `None` to make the field `null` in the output as the result of the transformation. + if str_input: + return output_type(re.search(r"\d+", str_input).group()) + else: + return None diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/graphql.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/graphql.py similarity index 97% rename from airbyte-integrations/connectors/source-shopify/source_shopify/graphql.py rename to airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/graphql.py index e8d38c64cdff..462ad3ea3aa8 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/graphql.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/graphql.py @@ -2,13 +2,14 @@ # Copyright (c) 2023 Airbyte, Inc., all rights reserved. # + from typing import Optional import sgqlc.operation -from . import shopify_schema +from . import schema -_schema = shopify_schema +_schema = schema _schema_root = _schema.shopify_schema diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_schema.py b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/schema.py similarity index 78% rename from airbyte-integrations/connectors/source-shopify/source_shopify/shopify_schema.py rename to airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/schema.py index 81966b99fc95..d3647a562084 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_schema.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/shopify_graphql/schema.py @@ -2,6 +2,7 @@ # Copyright (c) 2023 Airbyte, Inc., all rights reserved. # + import sgqlc.types import sgqlc.types.datetime import sgqlc.types.relay @@ -21,6 +22,31 @@ class ARN(sgqlc.types.Scalar): __schema__ = shopify_schema +class AbandonmentAbandonmentType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("BROWSE", "CART", "CHECKOUT") + + +class AbandonmentDeliveryState(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("NOT_SENT", "SCHEDULED", "SENT") + + +class AbandonmentEmailState(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("NOT_SENT", "SCHEDULED", "SENT") + + +class AbandonmentEmailStateUpdateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ABANDONMENT_NOT_FOUND",) + + +class AbandonmentUpdateActivitiesDeliveryStatusesUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ABANDONMENT_NOT_FOUND", "DELIVERY_STATUS_INFO_NOT_FOUND", "MARKETING_ACTIVITY_NOT_FOUND") + + class AppDeveloperType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("MERCHANT", "PARTNER", "SHOPIFY", "UNKNOWN") @@ -118,7 +144,16 @@ class BadgeType(sgqlc.types.Enum): class BillingAttemptUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("BLANK", "CONTRACT_NOT_FOUND", "INVALID") + __choices__ = ( + "BLANK", + "CONTRACT_NOT_FOUND", + "CYCLE_INDEX_OUT_OF_RANGE", + "CYCLE_START_DATE_OUT_OF_RANGE", + "INVALID", + "ORIGIN_TIME_BEFORE_CONTRACT_CREATION", + "ORIGIN_TIME_OUT_OF_RANGE", + "UPCOMING_CYCLE_LIMIT_EXCEEDED", + ) Boolean = sgqlc.types.Boolean @@ -126,13 +161,7 @@ class BillingAttemptUserErrorCode(sgqlc.types.Enum): class BulkMutationErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "INTERNAL_FILE_SERVER_ERROR", - "INVALID_MUTATION", - "INVALID_STAGED_UPLOAD_FILE", - "NO_SUCH_FILE", - "OPERATION_IN_PROGRESS", - ) + __choices__ = ("INTERNAL_FILE_SERVER_ERROR", "INVALID_MUTATION", "INVALID_STAGED_UPLOAD_FILE", "NO_SUCH_FILE", "OPERATION_IN_PROGRESS") class BulkOperationErrorCode(sgqlc.types.Enum): @@ -181,9 +210,75 @@ class BusinessCustomerErrorCode(sgqlc.types.Enum): ) +class CartTransformCreateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FUNCTION_ALREADY_REGISTERED", "FUNCTION_DOES_NOT_IMPLEMENT", "FUNCTION_NOT_FOUND", "INPUT_INVALID") + + +class CartTransformDeleteUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("NOT_FOUND", "UNAUTHORIZED_APP_SCOPE") + + +class CatalogSortKeys(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ID", "RELEVANCE", "TITLE") + + +class CatalogStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE", "ARCHIVED", "DRAFT") + + +class CatalogType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("APP", "COMPANY_LOCATION", "MARKET", "NONE") + + +class CatalogUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "APP_CATALOG_PRICE_LIST_ASSIGNMENT", + "BLANK", + "CANNOT_ADD_MORE_THAN_ONE_MARKET", + "CANNOT_CREATE_APP_CATALOG", + "CANNOT_CREATE_MARKET_CATALOG", + "CANNOT_DELETE_APP_CATALOG", + "CANNOT_DELETE_MARKET_CATALOG", + "CANNOT_MODIFY_APP_CATALOG", + "CANNOT_MODIFY_MARKET_CATALOG", + "CATALOG_CONTEXT_DOES_NOT_SUPPORT_QUANTITY_RULES", + "CATALOG_FAILED_TO_SAVE", + "CATALOG_NOT_FOUND", + "COMPANY_LOCATION_CATALOG_STATUS_PLAN", + "COMPANY_LOCATION_NOT_FOUND", + "CONTEXT_ALREADY_ASSIGNED_TO_CATALOG", + "CONTEXT_CATALOG_LIMIT_REACHED", + "CONTEXT_DRIVER_MISMATCH", + "COUNTRY_PRICE_LIST_ASSIGNMENT", + "INVALID", + "INVALID_CATALOG_CONTEXT_TYPE", + "MARKET_AND_PRICE_LIST_CURRENCY_MISMATCH", + "MARKET_CATALOG_STATUS", + "MARKET_NOT_FOUND", + "MARKET_TAKEN", + "MUST_PROVIDE_EXACTLY_ONE_CONTEXT_TYPE", + "PRICE_LIST_FAILED_TO_SAVE", + "PRICE_LIST_LOCKED", + "PRICE_LIST_NOT_ALLOWED_FOR_PRIMARY_MARKET", + "PRICE_LIST_NOT_FOUND", + "PUBLICATION_NOT_FOUND", + "REQUIRES_CONTEXTS_TO_ADD_OR_REMOVE", + "TAKEN", + "TOO_LONG", + "TOO_SHORT", + "UNSUPPORTED_CATALOG_ACTION", + ) + + class CheckoutProfileSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("CREATED_AT", "ID", "IS_PUBLISHED", "RELEVANCE", "UPDATED_AT") + __choices__ = ("CREATED_AT", "EDITED_AT", "ID", "IS_PUBLISHED", "RELEVANCE", "UPDATED_AT") class CodeDiscountSortKeys(sgqlc.types.Enum): @@ -200,12 +295,14 @@ class CollectionRuleColumn(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( "IS_PRICE_REDUCED", + "PRODUCT_METAFIELD_DEFINITION", "PRODUCT_TAXONOMY_NODE_ID", "TAG", "TITLE", "TYPE", "VARIANT_COMPARE_AT_PRICE", "VARIANT_INVENTORY", + "VARIANT_METAFIELD_DEFINITION", "VARIANT_PRICE", "VARIANT_TITLE", "VARIANT_WEIGHT", @@ -236,16 +333,7 @@ class CollectionSortKeys(sgqlc.types.Enum): class CollectionSortOrder(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "ALPHA_ASC", - "ALPHA_DESC", - "BEST_SELLING", - "CREATED", - "CREATED_DESC", - "MANUAL", - "PRICE_ASC", - "PRICE_DESC", - ) + __choices__ = ("ALPHA_ASC", "ALPHA_DESC", "BEST_SELLING", "CREATED", "CREATED_DESC", "MANUAL", "PRICE_ASC", "PRICE_DESC") class CompanyAddressType(sgqlc.types.Enum): @@ -728,16 +816,60 @@ class CustomerMarketingOptInLevel(sgqlc.types.Enum): __choices__ = ("CONFIRMED_OPT_IN", "SINGLE_OPT_IN", "UNKNOWN") -class CustomerPaymentMethodGetUpdateUrlUserErrorCode(sgqlc.types.Enum): +class CustomerMergeErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "CUSTOMER_HAS_GIFT_CARDS", + "INTERNAL_ERROR", + "INVALID_CUSTOMER", + "INVALID_CUSTOMER_ID", + "MISSING_OVERRIDE_ATTRIBUTE", + "OVERRIDE_ATTRIBUTE_INVALID", + ) + + +class CustomerMergeErrorFieldType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "COMPANY_CONTACT", + "CUSTOMER_PAYMENT_METHODS", + "DELETED_AT", + "GIFT_CARDS", + "MERGE_IN_PROGRESS", + "MULTIPASS_IDENTIFIER", + "PENDING_DATA_REQUEST", + "REDACTED_AT", + "SUBSCRIPTIONS", + ) + + +class CustomerMergeRequestStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("COMPLETED", "FAILED", "IN_PROGRESS", "REQUESTED") + + +class CustomerPaymentMethodCreateFromDuplicationDataUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CUSTOMER_DOES_NOT_EXIST", "INVALID_ENCRYPTED_DUPLICATION_DATA", "TOO_MANY_REQUESTS") + + +class CustomerPaymentMethodGetDuplicationDataUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( "CUSTOMER_DOES_NOT_EXIST", "INVALID_INSTRUMENT", + "INVALID_ORGANIZATION_SHOP", "PAYMENT_METHOD_DOES_NOT_EXIST", + "SAME_SHOP", "TOO_MANY_REQUESTS", ) +class CustomerPaymentMethodGetUpdateUrlUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CUSTOMER_DOES_NOT_EXIST", "INVALID_INSTRUMENT", "PAYMENT_METHOD_DOES_NOT_EXIST", "TOO_MANY_REQUESTS") + + class CustomerPaymentMethodRemoteUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -790,6 +922,11 @@ class CustomerSavedSearchSortKeys(sgqlc.types.Enum): __choices__ = ("ID", "NAME", "RELEVANCE") +class CustomerSegmentMembersQueryUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("INVALID",) + + class CustomerSmsMarketingConsentErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("INCLUSION", "INTERNAL_ERROR", "INVALID", "MISSING_ARGUMENT") @@ -802,17 +939,7 @@ class CustomerSmsMarketingState(sgqlc.types.Enum): class CustomerSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "CREATED_AT", - "ID", - "LAST_ORDER_DATE", - "LOCATION", - "NAME", - "ORDERS_COUNT", - "RELEVANCE", - "TOTAL_SPENT", - "UPDATED_AT", - ) + __choices__ = ("CREATED_AT", "ID", "LAST_ORDER_DATE", "LOCATION", "NAME", "ORDERS_COUNT", "RELEVANCE", "TOTAL_SPENT", "UPDATED_AT") class CustomerState(sgqlc.types.Enum): @@ -847,6 +974,11 @@ class DelegateAccessTokenCreateUserErrorCode(sgqlc.types.Enum): ) +class DelegateAccessTokenDestroyUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACCESS_DENIED", "ACCESS_TOKEN_NOT_FOUND", "CAN_ONLY_DELETE_DELEGATE_TOKENS", "PERSISTENCE_FAILED") + + class DeletionEventSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("CREATED_AT", "ID", "RELEVANCE") @@ -867,11 +999,39 @@ class DeliveryConditionOperator(sgqlc.types.Enum): __choices__ = ("GREATER_THAN_OR_EQUAL_TO", "LESS_THAN_OR_EQUAL_TO") +class DeliveryCustomizationErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "CUSTOM_APP_FUNCTION_NOT_ELIGIBLE", + "DELIVERY_CUSTOMIZATION_FUNCTION_NOT_ELIGIBLE", + "DELIVERY_CUSTOMIZATION_NOT_FOUND", + "FUNCTION_DOES_NOT_IMPLEMENT", + "FUNCTION_ID_CANNOT_BE_CHANGED", + "FUNCTION_NOT_FOUND", + "FUNCTION_PENDING_DELETION", + "INVALID", + "INVALID_METAFIELDS", + "MAXIMUM_ACTIVE_DELIVERY_CUSTOMIZATIONS", + "REQUIRED_INPUT_FIELD", + "UNAUTHORIZED_APP_SCOPE", + ) + + class DeliveryLegacyModeBlockedReason(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("NO_LOCATIONS_FULFILLING_ONLINE_ORDERS",) +class DeliveryLocalPickupTime(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FIVE_OR_MORE_DAYS", "FOUR_HOURS", "ONE_HOUR", "TWENTY_FOUR_HOURS", "TWO_HOURS", "TWO_TO_FOUR_DAYS") + + +class DeliveryLocationLocalPickupSettingsErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE_LOCATION_NOT_FOUND", "GENERIC_ERROR") + + class DeliveryMethodDefinitionType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("MERCHANT", "PARTICIPANT") @@ -1010,6 +1170,11 @@ class DraftOrderStatus(sgqlc.types.Enum): __choices__ = ("COMPLETED", "INVOICE_SENT", "OPEN") +class ErrorsServerPixelUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ALREADY_EXISTS", "NEEDS_CONFIGURATION_TO_CONNECT", "NOT_FOUND", "PUB_SUB_ERROR") + + class ErrorsWebPixelUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("BLANK", "INVALID_SETTINGS", "NOT_FOUND", "TAKEN", "UNABLE_TO_DELETE") @@ -1025,9 +1190,15 @@ class FileContentType(sgqlc.types.Enum): __choices__ = ("FILE", "IMAGE", "VIDEO") +class FileCreateInputDuplicateResolutionMode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("APPEND_UUID", "RAISE_ERROR", "REPLACE") + + class FileErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( + "DUPLICATE_FILENAME_ERROR", "EXTERNAL_VIDEO_EMBED_DISABLED", "EXTERNAL_VIDEO_EMBED_NOT_FOUND_OR_TRANSCODING", "EXTERNAL_VIDEO_INVALID_ASPECT_RATIO", @@ -1047,6 +1218,7 @@ class FileErrorCode(sgqlc.types.Enum): "MODEL3D_GLB_TO_USDZ_CONVERSION_ERROR", "MODEL3D_PROCESSING_FAILURE", "MODEL3D_THUMBNAIL_GENERATION_ERROR", + "MODEL3D_THUMBNAIL_REGENERATION_ERROR", "MODEL3D_VALIDATION_ERROR", "UNKNOWN", "UNSUPPORTED_IMAGE_FILE_TYPE", @@ -1064,7 +1236,7 @@ class FileErrorCode(sgqlc.types.Enum): class FileSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("CREATED_AT", "FILENAME", "ID", "ORIGINAL_UPLOAD_SIZE", "RELEVANCE") + __choices__ = ("CREATED_AT", "FILENAME", "ID", "ORIGINAL_UPLOAD_SIZE", "RELEVANCE", "UPDATED_AT") class FileStatus(sgqlc.types.Enum): @@ -1077,16 +1249,25 @@ class FilesErrorCode(sgqlc.types.Enum): __choices__ = ( "ALT_VALUE_LIMIT_EXCEEDED", "BLANK_SEARCH", + "FILENAME_ALREADY_EXISTS", "FILE_DOES_NOT_EXIST", "FILE_LOCKED", "INVALID", + "INVALID_DUPLICATE_MODE_FOR_TYPE", + "INVALID_FILENAME", + "INVALID_FILENAME_EXTENSION", + "INVALID_IMAGE_SOURCE_URL", "INVALID_QUERY", + "MISMATCHED_FILENAME_AND_ORIGINAL_SOURCE", "MISSING_ARGUMENTS", + "MISSING_FILENAME_FOR_DUPLICATE_MODE_REPLACE", "NON_IMAGE_MEDIA_PER_SHOP_LIMIT_EXCEEDED", + "NON_READY_STATE", "TOO_MANY_ARGUMENTS", "UNACCEPTABLE_ASSET", "UNACCEPTABLE_TRIAL_ASSET", "UNACCEPTABLE_UNVERIFIED_TRIAL_ASSET", + "UNSUPPORTED_MEDIA_TYPE_FOR_FILENAME_UPDATE", ) @@ -1146,6 +1327,7 @@ class FulfillmentHoldReason(sgqlc.types.Enum): "HIGH_RISK_OF_FRAUD", "INCORRECT_ADDRESS", "INVENTORY_OUT_OF_STOCK", + "ONLINE_STORE_POST_PURCHASE_CROSS_SELL", "OTHER", "UNKNOWN_DELIVERY_DATE", ) @@ -1159,10 +1341,12 @@ class FulfillmentOrderAction(sgqlc.types.Enum): "EXTERNAL", "HOLD", "MARK_AS_OPEN", + "MERGE", "MOVE", "RELEASE_HOLD", "REQUEST_CANCELLATION", "REQUEST_FULFILLMENT", + "SPLIT", ) @@ -1173,7 +1357,12 @@ class FulfillmentOrderAssignmentStatus(sgqlc.types.Enum): class FulfillmentOrderHoldUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND", "TAKEN") + __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND", "GREATER_THAN_ZERO", "INVALID_LINE_ITEM_QUANTITY", "TAKEN") + + +class FulfillmentOrderLineItemsPreparedForPickupUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FULFILLMENT_ORDER_INVALID", "NO_LINE_ITEMS_TO_PREPARE_FOR_FULFILLMENT_ORDER", "UNABLE_TO_PREPARE_QUANTITY") class FulfillmentOrderMerchantRequestKind(sgqlc.types.Enum): @@ -1181,20 +1370,19 @@ class FulfillmentOrderMerchantRequestKind(sgqlc.types.Enum): __choices__ = ("CANCELLATION_REQUEST", "FULFILLMENT_REQUEST") +class FulfillmentOrderMergeUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND", "GREATER_THAN", "INVALID_LINE_ITEM_QUANTITY") + + class FulfillmentOrderRejectionReason(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "INCORRECT_ADDRESS", - "INELIGIBLE_PRODUCT", - "INVENTORY_OUT_OF_STOCK", - "OTHER", - "UNDELIVERABLE_DESTINATION", - ) + __choices__ = ("INCORRECT_ADDRESS", "INELIGIBLE_PRODUCT", "INVENTORY_OUT_OF_STOCK", "OTHER", "UNDELIVERABLE_DESTINATION") class FulfillmentOrderReleaseHoldUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND",) + __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND", "GREATER_THAN_ZERO", "INVALID_LINE_ITEM_QUANTITY") class FulfillmentOrderRequestStatus(sgqlc.types.Enum): @@ -1221,11 +1409,21 @@ class FulfillmentOrderSortKeys(sgqlc.types.Enum): __choices__ = ("ID", "RELEVANCE") +class FulfillmentOrderSplitUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FULFILLMENT_ORDER_NOT_FOUND", "GREATER_THAN", "INVALID_LINE_ITEM_QUANTITY") + + class FulfillmentOrderStatus(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("CANCELLED", "CLOSED", "INCOMPLETE", "IN_PROGRESS", "ON_HOLD", "OPEN", "SCHEDULED") +class FulfillmentOrdersReleaseHoldsUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FAILED_TO_CREATE_JOB",) + + class FulfillmentOrdersSetFulfillmentDeadlineUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("FULFILLMENT_ORDERS_NOT_FOUND",) @@ -1278,15 +1476,256 @@ class ImageContentType(sgqlc.types.Enum): Int = sgqlc.types.Int +class InventoryAdjustQuantitiesUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "ADJUST_QUANTITIES_FAILED", + "INTERNAL_LEDGER_DOCUMENT", + "INVALID_AVAILABLE_DOCUMENT", + "INVALID_INVENTORY_ITEM", + "INVALID_LEDGER_DOCUMENT", + "INVALID_LOCATION", + "INVALID_QUANTITY_DOCUMENT", + "INVALID_QUANTITY_NAME", + "INVALID_QUANTITY_TOO_HIGH", + "INVALID_QUANTITY_TOO_LOW", + "INVALID_REASON", + "INVALID_REFERENCE_DOCUMENT", + "ITEM_NOT_STOCKED_AT_LOCATION", + "MAX_ONE_LEDGER_DOCUMENT", + "NON_MUTABLE_INVENTORY_ITEM", + ) + + class InventoryBulkToggleActivationUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("GENERIC_ERROR",) + __choices__ = ( + "CANNOT_DEACTIVATE_FROM_ONLY_LOCATION", + "COMMITTED_INVENTORY_AT_LOCATION", + "FAILED_TO_STOCK_AT_LOCATION", + "FAILED_TO_UNSTOCK_FROM_LOCATION", + "GENERIC_ERROR", + "INCOMING_INVENTORY_AT_LOCATION", + "INVENTORY_ITEM_NOT_FOUND", + "INVENTORY_MANAGED_BY_3RD_PARTY", + "INVENTORY_MANAGED_BY_SHOPIFY", + "LOCATION_NOT_FOUND", + "MISSING_SKU", + "RESERVED_INVENTORY_AT_LOCATION", + ) + + +class InventoryMoveQuantitiesUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "DIFFERENT_LOCATIONS", + "INTERNAL_LEDGER_DOCUMENT", + "INVALID_AVAILABLE_DOCUMENT", + "INVALID_INVENTORY_ITEM", + "INVALID_LEDGER_DOCUMENT", + "INVALID_LOCATION", + "INVALID_QUANTITY_DOCUMENT", + "INVALID_QUANTITY_NAME", + "INVALID_QUANTITY_NEGATIVE", + "INVALID_QUANTITY_TOO_HIGH", + "INVALID_REASON", + "INVALID_REFERENCE_DOCUMENT", + "ITEM_NOT_STOCKED_AT_LOCATION", + "MAXIMUM_LEDGER_DOCUMENT_URIS", + "MOVE_QUANTITIES_FAILED", + "NON_MUTABLE_INVENTORY_ITEM", + "SAME_QUANTITY_NAME", + ) + + +class InventorySetOnHandQuantitiesUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "INVALID_INVENTORY_ITEM", + "INVALID_LOCATION", + "INVALID_QUANTITY_NEGATIVE", + "INVALID_QUANTITY_TOO_HIGH", + "INVALID_REASON", + "INVALID_REFERENCE_DOCUMENT", + "ITEM_NOT_STOCKED_AT_LOCATION", + "NON_MUTABLE_INVENTORY_ITEM", + "SET_ON_HAND_QUANTITIES_FAILED", + ) class JSON(sgqlc.types.Scalar): __schema__ = shopify_schema +class LanguageCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "AF", + "AK", + "AM", + "AR", + "AS", + "AZ", + "BE", + "BG", + "BM", + "BN", + "BO", + "BR", + "BS", + "CA", + "CE", + "CS", + "CU", + "CY", + "DA", + "DE", + "DZ", + "EE", + "EL", + "EN", + "EO", + "ES", + "ET", + "EU", + "FA", + "FF", + "FI", + "FO", + "FR", + "FY", + "GA", + "GD", + "GL", + "GU", + "GV", + "HA", + "HE", + "HI", + "HR", + "HU", + "HY", + "IA", + "ID", + "IG", + "II", + "IS", + "IT", + "JA", + "JV", + "KA", + "KI", + "KK", + "KL", + "KM", + "KN", + "KO", + "KS", + "KU", + "KW", + "KY", + "LB", + "LG", + "LN", + "LO", + "LT", + "LU", + "LV", + "MG", + "MI", + "MK", + "ML", + "MN", + "MR", + "MS", + "MT", + "MY", + "NB", + "ND", + "NE", + "NL", + "NN", + "NO", + "OM", + "OR", + "OS", + "PA", + "PL", + "PS", + "PT", + "PT_BR", + "PT_PT", + "QU", + "RM", + "RN", + "RO", + "RU", + "RW", + "SD", + "SE", + "SG", + "SI", + "SK", + "SL", + "SN", + "SO", + "SQ", + "SR", + "SU", + "SV", + "SW", + "TA", + "TE", + "TG", + "TH", + "TI", + "TK", + "TO", + "TR", + "TT", + "UG", + "UK", + "UR", + "UZ", + "VI", + "VO", + "WO", + "XH", + "YI", + "YO", + "ZH", + "ZH_CN", + "ZH_TW", + "ZU", + ) + + +class LengthUnit(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CENTIMETERS", "FEET", "INCHES", "METERS", "MILLIMETERS", "YARDS") + + +class LocalizableContentType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "FILE_REFERENCE", + "HTML", + "INLINE_RICH_TEXT", + "JSON", + "JSON_STRING", + "LIST_FILE_REFERENCE", + "LIST_MULTI_LINE_TEXT_FIELD", + "LIST_SINGLE_LINE_TEXT_FIELD", + "LIST_URL", + "MULTI_LINE_TEXT_FIELD", + "RICH_TEXT_FIELD", + "SINGLE_LINE_TEXT_FIELD", + "STRING", + "URI", + "URL", + ) + + class LocalizationExtensionKey(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -1306,12 +1745,27 @@ class LocalizationExtensionPurpose(sgqlc.types.Enum): class LocationActivateUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("GENERIC_ERROR", "HAS_ONGOING_RELOCATION", "LOCATION_LIMIT", "LOCATION_NOT_FOUND") + __choices__ = ("GENERIC_ERROR", "HAS_NON_UNIQUE_NAME", "HAS_ONGOING_RELOCATION", "LOCATION_LIMIT", "LOCATION_NOT_FOUND") class LocationAddUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("BLANK", "GENERIC_ERROR", "INVALID", "INVALID_US_ZIPCODE", "TAKEN", "TOO_LONG") + __choices__ = ( + "APP_NOT_AUTHORIZED", + "BLANK", + "DISALLOWED_OWNER_TYPE", + "GENERIC_ERROR", + "INCLUSION", + "INVALID", + "INVALID_TYPE", + "INVALID_US_ZIPCODE", + "INVALID_VALUE", + "PRESENT", + "TAKEN", + "TOO_LONG", + "TOO_SHORT", + "UNSTRUCTURED_RESERVED_NAMESPACE", + ) class LocationDeactivateUserErrorCode(sgqlc.types.Enum): @@ -1330,7 +1784,6 @@ class LocationDeactivateUserErrorCode(sgqlc.types.Enum): "HAS_INCOMING_MOVEMENTS_ERROR", "HAS_OPEN_PURCHASE_ORDERS_ERROR", "HAS_OPEN_TRANSFERS_ERROR", - "INVALID", "LOCATION_NOT_FOUND", "PERMANENTLY_BLOCKED_FROM_DEACTIVATION_ERROR", "TEMPORARILY_BLOCKED_FROM_DEACTIVATION_ERROR", @@ -1352,13 +1805,22 @@ class LocationDeleteUserErrorCode(sgqlc.types.Enum): class LocationEditUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( + "APP_NOT_AUTHORIZED", "BLANK", "CANNOT_DISABLE_ONLINE_ORDER_FULFILLMENT", + "DISALLOWED_OWNER_TYPE", "GENERIC_ERROR", + "INCLUSION", "INVALID", + "INVALID_TYPE", "INVALID_US_ZIPCODE", + "INVALID_VALUE", "NOT_FOUND", - "TOO_LONG", + "PRESENT", + "TAKEN", + "TOO_LONG", + "TOO_SHORT", + "UNSTRUCTURED_RESERVED_NAMESPACE", ) @@ -1409,7 +1871,7 @@ class MarketUserErrorCode(sgqlc.types.Enum): "REQUIRES_DOMAIN_OR_SUBFOLDER", "REQUIRES_EXACTLY_ONE_OPTION", "SHOP_REACHED_MARKETS_LIMIT", - "SUBFOLDER_NOT_ALLOWED_FOR_CCTLD_DOMAINS", + "SUBFOLDER_SUFFIX_CANNOT_BE_SCRIPT_CODE", "SUBFOLDER_SUFFIX_MUST_CONTAIN_ONLY_LETTERS", "TAKEN", "TOO_LONG", @@ -1500,6 +1962,7 @@ class MediaContentType(sgqlc.types.Enum): class MediaErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( + "DUPLICATE_FILENAME_ERROR", "EXTERNAL_VIDEO_EMBED_DISABLED", "EXTERNAL_VIDEO_EMBED_NOT_FOUND_OR_TRANSCODING", "EXTERNAL_VIDEO_INVALID_ASPECT_RATIO", @@ -1519,6 +1982,7 @@ class MediaErrorCode(sgqlc.types.Enum): "MODEL3D_GLB_TO_USDZ_CONVERSION_ERROR", "MODEL3D_PROCESSING_FAILURE", "MODEL3D_THUMBNAIL_GENERATION_ERROR", + "MODEL3D_THUMBNAIL_REGENERATION_ERROR", "MODEL3D_VALIDATION_ERROR", "UNKNOWN", "UNSUPPORTED_IMAGE_FILE_TYPE", @@ -1585,6 +2049,11 @@ class MerchandiseDiscountClass(sgqlc.types.Enum): __choices__ = ("ORDER", "PRODUCT") +class MetafieldAdminAccess(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("MERCHANT_READ", "MERCHANT_READ_WRITE", "PRIVATE", "PUBLIC_READ") + + class MetafieldDefinitionCreateUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -1594,6 +2063,7 @@ class MetafieldDefinitionCreateUserErrorCode(sgqlc.types.Enum): "INVALID_CHARACTER", "INVALID_OPTION", "LIMIT_EXCEEDED", + "OWNER_TYPE_LIMIT_EXCEEDED_FOR_AUTOMATED_COLLECTIONS", "PINNED_LIMIT_REACHED", "PRESENT", "RESERVED_NAMESPACE_KEY", @@ -1601,18 +2071,26 @@ class MetafieldDefinitionCreateUserErrorCode(sgqlc.types.Enum): "TAKEN", "TOO_LONG", "TOO_SHORT", + "TYPE_NOT_ALLOWED_FOR_CONDITIONS", "UNSTRUCTURED_ALREADY_EXISTS", ) class MetafieldDefinitionDeleteUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("INTERNAL_ERROR", "NOT_FOUND", "PRESENT", "REFERENCE_TYPE_DELETION_ERROR") + __choices__ = ( + "DISALLOWED_OWNER_TYPE", + "INTERNAL_ERROR", + "METAFIELD_DEFINITION_IN_USE", + "NOT_FOUND", + "PRESENT", + "REFERENCE_TYPE_DELETION_ERROR", + ) class MetafieldDefinitionPinUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("ALREADY_PINNED", "INTERNAL_ERROR", "NOT_FOUND", "PINNED_LIMIT_REACHED") + __choices__ = ("ALREADY_PINNED", "DISALLOWED_OWNER_TYPE", "INTERNAL_ERROR", "NOT_FOUND", "PINNED_LIMIT_REACHED") class MetafieldDefinitionPinnedStatus(sgqlc.types.Enum): @@ -1627,12 +2105,22 @@ class MetafieldDefinitionSortKeys(sgqlc.types.Enum): class MetafieldDefinitionUnpinUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("INTERNAL_ERROR", "NOT_FOUND", "NOT_PINNED") + __choices__ = ("DISALLOWED_OWNER_TYPE", "INTERNAL_ERROR", "NOT_FOUND", "NOT_PINNED") class MetafieldDefinitionUpdateUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("INTERNAL_ERROR", "INVALID_INPUT", "NOT_FOUND", "PINNED_LIMIT_REACHED", "PRESENT", "TOO_LONG") + __choices__ = ( + "INTERNAL_ERROR", + "INVALID_INPUT", + "METAFIELD_DEFINITION_IN_USE", + "NOT_FOUND", + "OWNER_TYPE_LIMIT_EXCEEDED_FOR_AUTOMATED_COLLECTIONS", + "PINNED_LIMIT_REACHED", + "PRESENT", + "TOO_LONG", + "TYPE_NOT_ALLOWED_FOR_CONDITIONS", + ) class MetafieldDefinitionValidationStatus(sgqlc.types.Enum): @@ -1647,14 +2135,19 @@ class MetafieldOwnerType(sgqlc.types.Enum): "ARTICLE", "BLOG", "COLLECTION", + "COMPANY", + "COMPANY_LOCATION", "CUSTOMER", + "DELIVERY_CUSTOMIZATION", "DISCOUNT", "DRAFTORDER", "LOCATION", + "MARKET", + "MEDIA_IMAGE", "ORDER", "PAGE", + "PAYMENT_CUSTOMIZATION", "PRODUCT", - "PRODUCTIMAGE", "PRODUCTVARIANT", "SHOP", ) @@ -1685,6 +2178,50 @@ class MetafieldsSetUserErrorCode(sgqlc.types.Enum): ) +class MetaobjectAdminAccess(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("MERCHANT_READ", "MERCHANT_READ_WRITE", "PRIVATE", "PUBLIC_READ", "PUBLIC_READ_WRITE") + + +class MetaobjectStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE", "DRAFT") + + +class MetaobjectStorefrontAccess(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("NONE", "PUBLIC_READ") + + +class MetaobjectUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "BLANK", + "CAPABILITY_NOT_ENABLED", + "DUPLICATE_FIELD_INPUT", + "IMMUTABLE", + "INCLUSION", + "INTERNAL_ERROR", + "INVALID", + "INVALID_OPTION", + "INVALID_TYPE", + "INVALID_VALUE", + "MAX_DEFINITIONS_EXCEEDED", + "MAX_OBJECTS_EXCEEDED", + "NOT_AUTHORIZED", + "OBJECT_FIELD_REQUIRED", + "OBJECT_FIELD_TAKEN", + "PRESENT", + "RECORD_NOT_FOUND", + "RESERVED_NAME", + "TAKEN", + "TOO_LONG", + "TOO_SHORT", + "UNDEFINED_OBJECT_FIELD", + "UNDEFINED_OBJECT_TYPE", + ) + + class MethodDefinitionSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("ID", "RATE_PROVIDER_TYPE", "RELEVANCE") @@ -1711,16 +2248,7 @@ class OrderCreateMandatePaymentUserErrorCode(sgqlc.types.Enum): class OrderDisplayFinancialStatus(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "AUTHORIZED", - "EXPIRED", - "PAID", - "PARTIALLY_PAID", - "PARTIALLY_REFUNDED", - "PENDING", - "REFUNDED", - "VOIDED", - ) + __choices__ = ("AUTHORIZED", "EXPIRED", "PAID", "PARTIALLY_PAID", "PARTIALLY_REFUNDED", "PENDING", "REFUNDED", "VOIDED") class OrderDisplayFulfillmentStatus(sgqlc.types.Enum): @@ -1760,6 +2288,11 @@ class OrderPaymentStatusResult(sgqlc.types.Enum): ) +class OrderReturnStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("INSPECTION_COMPLETE", "IN_PROGRESS", "NO_RETURN", "RETURNED", "RETURN_FAILED", "RETURN_REQUESTED") + + class OrderRiskLevel(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("HIGH", "LOW", "MEDIUM") @@ -1770,12 +2303,15 @@ class OrderSortKeys(sgqlc.types.Enum): __choices__ = ( "CREATED_AT", "CUSTOMER_NAME", + "DESTINATION", "FINANCIAL_STATUS", "FULFILLMENT_STATUS", "ID", "ORDER_NUMBER", + "PO_NUMBER", "PROCESSED_AT", "RELEVANCE", + "TOTAL_ITEMS_QUANTITY", "TOTAL_PRICE", "UPDATED_AT", ) @@ -1816,16 +2352,7 @@ class OrderTransactionErrorCode(sgqlc.types.Enum): class OrderTransactionKind(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "AUTHORIZATION", - "CAPTURE", - "CHANGE", - "EMV_AUTHORIZATION", - "REFUND", - "SALE", - "SUGGESTED_REFUND", - "VOID", - ) + __choices__ = ("AUTHORIZATION", "CAPTURE", "CHANGE", "EMV_AUTHORIZATION", "REFUND", "SALE", "SUGGESTED_REFUND", "VOID") class OrderTransactionStatus(sgqlc.types.Enum): @@ -1833,6 +2360,76 @@ class OrderTransactionStatus(sgqlc.types.Enum): __choices__ = ("AWAITING_RESPONSE", "ERROR", "FAILURE", "PENDING", "SUCCESS", "UNKNOWN") +class ParseErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "BACKFILL_DATE_RANGE_NOT_FOUND", + "COLUMN_NOT_FOUND", + "COMPARE_TO_INCOMPATIBLE_PERIOD", + "COMPARE_TO_INVALID_PERIOD", + "COMPARE_TO_MISSING_PERIOD", + "COMPARISON_WITH_NON_AGGREGATE_FIELDS", + "DATE_INTERVAL_NOT_FOUND", + "DATE_NOT_PARSABLE", + "DATE_TIME_NOT_PARSABLE", + "EXCESS_BACKFILL_DIMENSIONS", + "EXCESS_DIMENSIONS", + "EXCESS_PERIODS", + "EXCESS_PRESENTMENTS", + "FROM_NOT_FOUND", + "FUNCTION_ARGUMENTS_NOT_FOUND", + "FUNCTION_EXCESS_ARGUMENTS", + "FUNCTION_INCOMPATIBLE_TYPES", + "FUNCTION_MODIFIER_NOT_FOUND", + "FUNCTION_NESTED_AGGREGATE", + "FUNCTION_NOT_FOUND", + "INVALID_DATE_RANGE", + "LIMIT_INVALID", + "LIST_MIXED_ARGUMENT_TYPES", + "MIXED_AGGREGATE_AND_NON_AGGREGATE", + "NAMED_DATE_NOT_FOUND", + "OPERATOR_INCOMPATIBLE_TYPES", + "PRESENTMENT_NOT_FOUND", + "REQUIRED_GROUP_BY_NOT_FOUND", + "SEMANTICALLY_INVALID", + "SORT_FIELD_NOT_FOUND", + "SYNTAX_FAILED_PREDICATE", + "SYNTAX_INPUT_MISMATCH", + "SYNTAX_INVALID_TOKEN", + "SYNTAX_MISSING_TOKEN", + "SYNTAX_NOT_RECOGNIZED", + "SYNTAX_NO_VIABLE_ALTERNATIVE", + "SYNTAX_UNWANTED_TOKEN", + "TABLE_NOT_FOUND", + "TIME_FUNCTION_NOT_FOUND", + "UNBACKFILLED_TIME_GROUP_BY_COMPARISON", + "UNKNOWN", + "VALUE_NOT_PARSABLE", + "VISUALIZE_CHART_TYPE_NOT_FOUND", + "VISUALIZE_EXCESS_PROJECTIONS", + "VISUALIZE_GROUP_BY_MIXED_BACKFILL", + "VISUALIZE_GROUP_BY_NOT_FOUND", + "VISUALIZE_INCOMPATIBLE_TYPES", + ) + + +class PaymentCustomizationErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "CUSTOM_APP_FUNCTION_NOT_ELIGIBLE", + "FUNCTION_DOES_NOT_IMPLEMENT", + "FUNCTION_ID_CANNOT_BE_CHANGED", + "FUNCTION_NOT_FOUND", + "FUNCTION_PENDING_DELETION", + "INVALID", + "INVALID_METAFIELDS", + "MAXIMUM_ACTIVE_PAYMENT_CUSTOMIZATIONS", + "PAYMENT_CUSTOMIZATION_FUNCTION_NOT_ELIGIBLE", + "PAYMENT_CUSTOMIZATION_NOT_FOUND", + "REQUIRED_INPUT_FIELD", + ) + + class PaymentMethods(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -1843,6 +2440,7 @@ class PaymentMethods(sgqlc.types.Enum): "DINERS_CLUB", "DISCOVER", "DOGECOIN", + "EFTPOS", "ELO", "FORBRUGSFORENINGEN", "INTERAC", @@ -1856,6 +2454,11 @@ class PaymentMethods(sgqlc.types.Enum): ) +class PaymentReminderSendUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("PAYMENT_REMINDER_SEND_UNSUCCESSFUL",) + + class PaymentTermsCreateUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("PAYMENT_TERMS_CREATION_UNSUCCESSFUL",) @@ -1868,7 +2471,7 @@ class PaymentTermsDeleteUserErrorCode(sgqlc.types.Enum): class PaymentTermsType(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("FIXED", "NET", "RECEIPT", "UNKNOWN") + __choices__ = ("FIXED", "FULFILLMENT", "NET", "RECEIPT", "UNKNOWN") class PaymentTermsUpdateUserErrorCode(sgqlc.types.Enum): @@ -1881,11 +2484,34 @@ class PaypalExpressSubscriptionsGatewayStatus(sgqlc.types.Enum): __choices__ = ("DISABLED", "ENABLED", "PENDING") +class PriceCalculationType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("COMPONENTS_SUM", "FIXED", "NONE") + + class PriceListAdjustmentType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("PERCENTAGE_DECREASE", "PERCENTAGE_INCREASE") +class PriceListCompareAtMode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ADJUSTED", "NULLIFY") + + +class PriceListFixedPricesByProductBulkUpdateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "DUPLICATE_ID_IN_INPUT", + "ID_MUST_BE_MUTUALLY_EXCLUSIVE", + "NO_UPDATE_OPERATIONS_SPECIFIED", + "PRICES_TO_ADD_CURRENCY_MISMATCH", + "PRICE_LIMIT_EXCEEDED", + "PRICE_LIST_DOES_NOT_EXIST", + "PRODUCT_DOES_NOT_EXIST", + ) + + class PriceListPriceOriginType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("FIXED", "RELATIVE") @@ -1893,13 +2519,7 @@ class PriceListPriceOriginType(sgqlc.types.Enum): class PriceListPriceUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "BLANK", - "PRICE_LIST_CURRENCY_MISMATCH", - "PRICE_LIST_NOT_FOUND", - "PRICE_NOT_FIXED", - "VARIANT_NOT_FOUND", - ) + __choices__ = ("BLANK", "PRICE_LIST_CURRENCY_MISMATCH", "PRICE_LIST_NOT_FOUND", "PRICE_NOT_FIXED", "VARIANT_NOT_FOUND") class PriceListSortKeys(sgqlc.types.Enum): @@ -1910,20 +2530,35 @@ class PriceListSortKeys(sgqlc.types.Enum): class PriceListUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( + "APP_CATALOG_PRICE_LIST_ASSIGNMENT", + "BLANK", + "CATALOG_ASSIGNMENT_NOT_ALLOWED", + "CATALOG_CANNOT_CHANGE_CONTEXT_TYPE", + "CATALOG_CONTEXT_DOES_NOT_SUPPORT_QUANTITY_RULES", + "CATALOG_DOES_NOT_EXIST", + "CATALOG_MARKET_AND_PRICE_LIST_CURRENCY_MISMATCH", + "CATALOG_TAKEN", "CONTEXT_RULE_COUNTRIES_LIMIT", "CONTEXT_RULE_COUNTRY_TAKEN", "CONTEXT_RULE_LIMIT_ONE_OPTION", "CONTEXT_RULE_MARKET_NOT_FOUND", "CONTEXT_RULE_MARKET_TAKEN", "COUNTRY_CURRENCY_MISMATCH", + "COUNTRY_PRICE_LIST_ASSIGNMENT", "CURRENCY_COUNTRY_MISMATCH", "CURRENCY_MARKET_MISMATCH", "CURRENCY_NOT_SUPPORTED", + "GENERIC_ERROR", + "INCLUSION", + "INVALID_ADJUSTMENT_MAX_VALUE", + "INVALID_ADJUSTMENT_MIN_VALUE", "INVALID_ADJUSTMENT_VALUE", "MARKET_CURRENCY_MISMATCH", + "PRICE_LIST_LOCKED", "PRICE_LIST_NOT_ALLOWED_FOR_PRIMARY_MARKET", "PRICE_LIST_NOT_FOUND", "TAKEN", + "TOO_LONG", ) @@ -2015,13 +2650,7 @@ class PriceRuleErrorCode(sgqlc.types.Enum): class PriceRuleFeature(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "BULK", - "BUY_ONE_GET_ONE", - "BUY_ONE_GET_ONE_WITH_ALLOCATION_LIMIT", - "QUANTITY_DISCOUNTS", - "SPECIFIC_CUSTOMERS", - ) + __choices__ = ("BULK", "BUY_ONE_GET_ONE", "BUY_ONE_GET_ONE_WITH_ALLOCATION_LIMIT", "QUANTITY_DISCOUNTS", "SPECIFIC_CUSTOMERS") class PriceRuleShareableUrlTargetType(sgqlc.types.Enum): @@ -2046,13 +2675,7 @@ class PriceRuleTarget(sgqlc.types.Enum): class PriceRuleTrait(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "BULK", - "BUY_ONE_GET_ONE", - "BUY_ONE_GET_ONE_WITH_ALLOCATION_LIMIT", - "QUANTITY_DISCOUNTS", - "SPECIFIC_CUSTOMERS", - ) + __choices__ = ("BULK", "BUY_ONE_GET_ONE", "BUY_ONE_GET_ONE_WITH_ALLOCATION_LIMIT", "QUANTITY_DISCOUNTS", "SPECIFIC_CUSTOMERS") class PrivateMetafieldValueType(sgqlc.types.Enum): @@ -2070,6 +2693,36 @@ class ProductCollectionSortKeys(sgqlc.types.Enum): __choices__ = ("BEST_SELLING", "COLLECTION_DEFAULT", "CREATED", "ID", "MANUAL", "PRICE", "RELEVANCE", "TITLE") +class ProductDeleteUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("GENERIC_ERROR", "PRODUCT_DOES_NOT_EXIST") + + +class ProductDuplicateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("BUNDLES_ERROR", "EMPTY_TITLE", "EMPTY_VARIANT", "FAILED_TO_SAVE", "GENERIC_ERROR", "PRODUCT_DOES_NOT_EXIST") + + +class ProductFeedCreateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("INVALID", "TAKEN") + + +class ProductFeedDeleteUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("INVALID",) + + +class ProductFeedStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE", "INACTIVE") + + +class ProductFullSyncUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("INVALID",) + + class ProductImageSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("CREATED_AT", "ID", "POSITION", "RELEVANCE") @@ -2082,17 +2735,7 @@ class ProductMediaSortKeys(sgqlc.types.Enum): class ProductSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "CREATED_AT", - "ID", - "INVENTORY_TOTAL", - "PRODUCT_TYPE", - "PUBLISHED_AT", - "RELEVANCE", - "TITLE", - "UPDATED_AT", - "VENDOR", - ) + __choices__ = ("CREATED_AT", "ID", "INVENTORY_TOTAL", "PRODUCT_TYPE", "PUBLISHED_AT", "RELEVANCE", "TITLE", "UPDATED_AT", "VENDOR") class ProductStatus(sgqlc.types.Enum): @@ -2110,6 +2753,32 @@ class ProductVariantInventoryPolicy(sgqlc.types.Enum): __choices__ = ("CONTINUE", "DENY") +class ProductVariantRelationshipBulkUpdateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "CIRCULAR_REFERENCE", + "DUPLICATE_PRODUCT_VARIANT_RELATIONSHIP", + "EXCEEDED_PRODUCT_VARIANT_RELATIONSHIP_LIMIT", + "FAILED_TO_CREATE", + "FAILED_TO_REMOVE", + "FAILED_TO_UPDATE", + "FAILED_TO_UPDATE_PARENT_PRODUCT_VARIANT_PRICE", + "INVALID_QUANTITY", + "MUST_SPECIFY_COMPONENTS", + "NESTED_PARENT_PRODUCT_VARIANT", + "PARENT_PRODUCT_VARIANT_CANNOT_BE_GIFT_CARD", + "PARENT_PRODUCT_VARIANT_CANNOT_REQUIRE_SELLING_PLAN", + "PARENT_REQUIRED", + "PRODUCT_EXPANDER_APP_OWNERSHIP_ALREADY_EXISTS", + "PRODUCT_VARIANTS_NOT_COMPONENTS", + "PRODUCT_VARIANTS_NOT_FOUND", + "PRODUCT_VARIANT_RELATIONSHIP_TYPE_CONFLICT", + "UNEXPECTED_ERROR", + "UNSUPPORTED_MULTIPACK_RELATIONSHIP", + "UPDATE_PARENT_VARIANT_PRICE_REQUIRED", + ) + + class ProductVariantSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -2150,11 +2819,7 @@ class ProductVariantsBulkCreateUserErrorCode(sgqlc.types.Enum): class ProductVariantsBulkDeleteUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "AT_LEAST_ONE_VARIANT_DOES_NOT_BELONG_TO_THE_PRODUCT", - "CANNOT_DELETE_LAST_VARIANT", - "PRODUCT_DOES_NOT_EXIST", - ) + __choices__ = ("AT_LEAST_ONE_VARIANT_DOES_NOT_BELONG_TO_THE_PRODUCT", "CANNOT_DELETE_LAST_VARIANT", "PRODUCT_DOES_NOT_EXIST") class ProductVariantsBulkReorderUserErrorCode(sgqlc.types.Enum): @@ -2181,17 +2846,7 @@ class ProductVariantsBulkUpdateUserErrorCode(sgqlc.types.Enum): class ProfileItemSortKeys(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ( - "CREATED_AT", - "ID", - "INVENTORY_TOTAL", - "PRODUCT_TYPE", - "PUBLISHED_AT", - "RELEVANCE", - "TITLE", - "UPDATED_AT", - "VENDOR", - ) + __choices__ = ("CREATED_AT", "ID", "INVENTORY_TOTAL", "PRODUCT_TYPE", "PUBLISHED_AT", "RELEVANCE", "TITLE", "UPDATED_AT", "VENDOR") class PubSubWebhookSubscriptionCreateUserErrorCode(sgqlc.types.Enum): @@ -2204,6 +2859,57 @@ class PubSubWebhookSubscriptionUpdateUserErrorCode(sgqlc.types.Enum): __choices__ = ("INVALID_PARAMETERS",) +class PublicationCreateInputPublicationDefaultState(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ALL_PRODUCTS", "EMPTY") + + +class PublicationUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "BLANK", + "CANNOT_MODIFY_APP_CATALOG", + "CANNOT_MODIFY_APP_CATALOG_PUBLICATION", + "CANNOT_MODIFY_MARKET_CATALOG", + "CANNOT_MODIFY_MARKET_CATALOG_PUBLICATION", + "CATALOG_NOT_FOUND", + "INVALID", + "INVALID_PUBLISHABLE_ID", + "MARKET_NOT_FOUND", + "PRODUCT_TYPE_INCOMPATIBLE_WITH_CATALOG_TYPE", + "PUBLICATION_LOCKED", + "PUBLICATION_NOT_FOUND", + "PUBLICATION_UPDATE_LIMIT_EXCEEDED", + "TAKEN", + "TOO_LONG", + "TOO_SHORT", + "UNSUPPORTED_PUBLICATION_ACTION", + "UNSUPPORTED_PUBLISHABLE_TYPE", + ) + + +class QuantityRuleOriginType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FIXED", "RELATIVE") + + +class QuantityRuleUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "BLANK", + "CATALOG_CONTEXT_DOES_NOT_SUPPORT_QUANTITY_RULES", + "GENERIC_ERROR", + "GREATER_THAN_OR_EQUAL_TO", + "INCREMENT_IS_GREATER_THAN_MINIMUM", + "MAXIMUM_NOT_MULTIPLE_OF_INCREMENT", + "MINIMUM_IS_GREATER_THAN_MAXIMUM", + "MINIMUM_NOT_MULTIPLE_OF_INCREMENT", + "PRICE_LIST_DOES_NOT_EXIST", + "PRODUCT_VARIANT_DOES_NOT_EXIST", + "VARIANT_QUANTITY_RULE_DOES_NOT_EXIST", + ) + + class RefundDutyRefundType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("FULL", "PROPORTIONAL") @@ -2229,6 +2935,82 @@ class ResourceFeedbackState(sgqlc.types.Enum): __choices__ = ("ACCEPTED", "REQUIRES_ACTION") +class ResourceOperationStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE", "COMPLETE", "CREATED") + + +class ReturnDeclineReason(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("FINAL_SALE", "OTHER", "RETURN_PERIOD_ENDED") + + +class ReturnErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "ALREADY_EXISTS", + "BLANK", + "CREATION_FAILED", + "EQUAL_TO", + "FEATURE_NOT_ENABLED", + "GREATER_THAN", + "GREATER_THAN_OR_EQUAL_TO", + "INCLUSION", + "INTERNAL_ERROR", + "INVALID", + "INVALID_STATE", + "LESS_THAN", + "LESS_THAN_OR_EQUAL_TO", + "NOTIFICATION_FAILED", + "NOT_A_NUMBER", + "NOT_EDITABLE", + "NOT_FOUND", + "PRESENT", + "TAKEN", + "TOO_BIG", + "TOO_LONG", + "TOO_MANY_ARGUMENTS", + "TOO_SHORT", + "WRONG_LENGTH", + ) + + +class ReturnReason(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ( + "COLOR", + "DEFECTIVE", + "NOT_AS_DESCRIBED", + "OTHER", + "SIZE_TOO_LARGE", + "SIZE_TOO_SMALL", + "STYLE", + "UNKNOWN", + "UNWANTED", + "WRONG_ITEM", + ) + + +class ReturnStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CANCELED", "CLOSED", "DECLINED", "OPEN", "REQUESTED") + + +class ReverseFulfillmentOrderDispositionType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("MISSING", "NOT_RESTOCKED", "PROCESSING_REQUIRED", "RESTOCKED") + + +class ReverseFulfillmentOrderStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CANCELED", "CLOSED", "OPEN") + + +class ReverseFulfillmentOrderThirdPartyConfirmationStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACCEPTED", "CANCEL_ACCEPTED", "CANCEL_REJECTED", "PENDING_ACCEPTANCE", "PENDING_CANCELATION", "REJECTED") + + class SaleActionType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("ORDER", "RETURN", "UNKNOWN", "UPDATE") @@ -2236,7 +3018,7 @@ class SaleActionType(sgqlc.types.Enum): class SaleLineType(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("ADJUSTMENT", "DUTY", "GIFT_CARD", "PRODUCT", "SHIPPING", "TIP", "UNKNOWN") + __choices__ = ("ADDITIONAL_FEE", "ADJUSTMENT", "DUTY", "GIFT_CARD", "PRODUCT", "SHIPPING", "TIP", "UNKNOWN") class ScriptTagDisplayScope(sgqlc.types.Enum): @@ -2398,11 +3180,21 @@ class SellingPlanReserve(sgqlc.types.Enum): __choices__ = ("ON_FULFILLMENT", "ON_SALE") +class ServerPixelStatus(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CONNECTED", "DISCONNECTED_CONFIGURED", "DISCONNECTED_UNCONFIGURED") + + class ShippingDiscountClass(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("SHIPPING",) +class ShippingPackageType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("BOX", "ENVELOPE", "FLAT_RATE", "SOFT_PACK") + + class ShopBranding(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("ROGERS", "SHOPIFY", "SHOPIFY_GOLD", "SHOPIFY_PLUS") @@ -2421,6 +3213,7 @@ class ShopPolicyErrorCode(sgqlc.types.Enum): class ShopPolicyType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( + "CONTACT_INFORMATION", "LEGAL_NOTICE", "PRIVACY_POLICY", "REFUND_POLICY", @@ -2431,6 +3224,11 @@ class ShopPolicyType(sgqlc.types.Enum): ) +class ShopResourceFeedbackCreateUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("BLANK", "INVALID", "OUTDATED_FEEDBACK", "PRESENT") + + class ShopTagSort(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("ALPHABETICAL", "POPULAR") @@ -2542,6 +3340,7 @@ class StagedUploadTargetGenerateUploadResource(sgqlc.types.Enum): "IMAGE", "MODEL_3D", "PRODUCT_IMAGE", + "RETURN_LABEL", "SHOP_IMAGE", "URL_REDIRECT_IMPORT", "VIDEO", @@ -2550,7 +3349,14 @@ class StagedUploadTargetGenerateUploadResource(sgqlc.types.Enum): class StandardMetafieldDefinitionEnableUserErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("INVALID", "LIMIT_EXCEEDED", "TAKEN", "TEMPLATE_NOT_FOUND", "UNSTRUCTURED_ALREADY_EXISTS") + __choices__ = ( + "INVALID", + "LIMIT_EXCEEDED", + "TAKEN", + "TEMPLATE_NOT_FOUND", + "TYPE_NOT_ALLOWED_FOR_CONDITIONS", + "UNSTRUCTURED_ALREADY_EXISTS", + ) class StorefrontID(sgqlc.types.Scalar): @@ -2572,16 +3378,23 @@ class SubscriptionBillingAttemptErrorCode(sgqlc.types.Enum): "INVALID_CUSTOMER_BILLING_AGREEMENT", "INVALID_PAYMENT_METHOD", "INVALID_SHIPPING_ADDRESS", + "INVENTORY_ALLOCATIONS_NOT_FOUND", "INVOICE_ALREADY_PAID", "PAYMENT_METHOD_DECLINED", "PAYMENT_METHOD_INCOMPATIBLE_WITH_GATEWAY_CONFIG", "PAYMENT_METHOD_NOT_FOUND", "PAYMENT_PROVIDER_IS_NOT_ENABLED", "TEST_MODE", + "TRANSIENT_ERROR", "UNEXPECTED_ERROR", ) +class SubscriptionBillingAttemptsSortKeys(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("CREATED_AT", "ID", "RELEVANCE") + + class SubscriptionBillingCycleBillingCycleStatus(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("BILLED", "UNBILLED") @@ -2591,13 +3404,17 @@ class SubscriptionBillingCycleErrorCode(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( "BILLING_DATE_SET_ON_SKIPPED", + "CYCLE_INDEX_OUT_OF_RANGE", "CYCLE_NOT_FOUND", + "CYCLE_START_DATE_OUT_OF_RANGE", "EMPTY_BILLING_CYCLE_EDIT_SCHEDULE_INPUT", + "INCOMPLETE_BILLING_ATTEMPTS", "INVALID", "INVALID_CYCLE_INDEX", "INVALID_DATE", "NO_CYCLE_EDITS", "OUT_OF_BOUNDS", + "UPCOMING_CYCLE_LIMIT_EXCEEDED", ) @@ -2628,7 +3445,7 @@ class SubscriptionContractLastPaymentStatus(sgqlc.types.Enum): class SubscriptionContractSubscriptionStatus(sgqlc.types.Enum): __schema__ = shopify_schema - __choices__ = ("ACTIVE", "CANCELLED", "EXPIRED", "FAILED", "PAUSED") + __choices__ = ("ACTIVE", "CANCELLED", "EXPIRED", "FAILED", "PAUSED", "STALE") class SubscriptionDiscountRejectionReason(sgqlc.types.Enum): @@ -2681,6 +3498,7 @@ class SubscriptionDraftErrorCode(sgqlc.types.Enum): "INVALID_NOTE_LENGTH", "LESS_THAN", "LESS_THAN_OR_EQUAL_TO", + "MISSING_LOCAL_DELIVERY_OPTIONS", "NOT_AN_INTEGER", "NOT_IN_RANGE", "NO_ENTITLED_LINES", @@ -2698,6 +3516,11 @@ class SuggestedOrderTransactionKind(sgqlc.types.Enum): __choices__ = ("SUGGESTED_REFUND",) +class TaxAppConfigureUserErrorCode(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("TAX_PARTNER_ALREADY_ACTIVE", "TAX_PARTNER_NOT_FOUND", "TAX_PARTNER_STATE_UPDATE_FAILED") + + class TaxExemption(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( @@ -2776,14 +3599,21 @@ class TaxExemption(sgqlc.types.Enum): ) +class TaxPartnerState(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("ACTIVE", "PENDING", "READY") + + class TranslatableResourceType(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ( "COLLECTION", "DELIVERY_METHOD_DEFINITION", "EMAIL_TEMPLATE", + "FILTER", "LINK", "METAFIELD", + "METAOBJECT", "ONLINE_STORE_ARTICLE", "ONLINE_STORE_BLOG", "ONLINE_STORE_MENU", @@ -2814,11 +3644,13 @@ class TranslationErrorCode(sgqlc.types.Enum): "INVALID_LOCALE_FOR_SHOP", "INVALID_MARKET_LOCALIZABLE_CONTENT", "INVALID_TRANSLATABLE_CONTENT", + "INVALID_VALUE_FOR_HANDLE_TRANSLATION", "MARKET_CUSTOM_CONTENT_NOT_ALLOWED", "MARKET_DOES_NOT_EXIST", "MARKET_LOCALE_CREATION_FAILED", "RESOURCE_NOT_FOUND", "RESOURCE_NOT_MARKET_CUSTOMIZABLE", + "RESOURCE_NOT_TRANSLATABLE", "TOO_MANY_KEYS_FOR_RESOURCE", ) @@ -2870,6 +3702,11 @@ class UtcOffset(sgqlc.types.Scalar): __schema__ = shopify_schema +class VisualizationType(sgqlc.types.Enum): + __schema__ = shopify_schema + __choices__ = ("BAR", "LINE") + + class WebhookSubscriptionFormat(sgqlc.types.Enum): __schema__ = shopify_schema __choices__ = ("JSON", "XML") @@ -2889,6 +3726,7 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "APP_UNINSTALLED", "ATTRIBUTED_SESSIONS_FIRST", "ATTRIBUTED_SESSIONS_LAST", + "AUDIT_EVENTS_ADMIN_API_ACTIVITY", "BULK_OPERATIONS_FINISH", "CARTS_CREATE", "CARTS_UPDATE", @@ -2905,11 +3743,24 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "COLLECTION_PUBLICATIONS_CREATE", "COLLECTION_PUBLICATIONS_DELETE", "COLLECTION_PUBLICATIONS_UPDATE", + "COMPANIES_CREATE", + "COMPANIES_DELETE", + "COMPANIES_UPDATE", + "COMPANY_CONTACTS_CREATE", + "COMPANY_CONTACTS_DELETE", + "COMPANY_CONTACTS_UPDATE", + "COMPANY_CONTACT_ROLES_ASSIGN", + "COMPANY_CONTACT_ROLES_REVOKE", + "COMPANY_LOCATIONS_CREATE", + "COMPANY_LOCATIONS_DELETE", + "COMPANY_LOCATIONS_UPDATE", "CUSTOMERS_CREATE", "CUSTOMERS_DELETE", "CUSTOMERS_DISABLE", + "CUSTOMERS_EMAIL_MARKETING_CONSENT_UPDATE", "CUSTOMERS_ENABLE", "CUSTOMERS_MARKETING_CONSENT_UPDATE", + "CUSTOMERS_MERGE", "CUSTOMERS_UPDATE", "CUSTOMER_GROUPS_CREATE", "CUSTOMER_GROUPS_DELETE", @@ -2917,6 +3768,8 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "CUSTOMER_PAYMENT_METHODS_CREATE", "CUSTOMER_PAYMENT_METHODS_REVOKE", "CUSTOMER_PAYMENT_METHODS_UPDATE", + "CUSTOMER_TAGS_ADDED", + "CUSTOMER_TAGS_REMOVED", "DISPUTES_CREATE", "DISPUTES_UPDATE", "DOMAINS_CREATE", @@ -2929,6 +3782,22 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "FULFILLMENTS_UPDATE", "FULFILLMENT_EVENTS_CREATE", "FULFILLMENT_EVENTS_DELETE", + "FULFILLMENT_ORDERS_CANCELLATION_REQUEST_ACCEPTED", + "FULFILLMENT_ORDERS_CANCELLATION_REQUEST_REJECTED", + "FULFILLMENT_ORDERS_CANCELLATION_REQUEST_SUBMITTED", + "FULFILLMENT_ORDERS_CANCELLED", + "FULFILLMENT_ORDERS_FULFILLMENT_REQUEST_ACCEPTED", + "FULFILLMENT_ORDERS_FULFILLMENT_REQUEST_REJECTED", + "FULFILLMENT_ORDERS_FULFILLMENT_REQUEST_SUBMITTED", + "FULFILLMENT_ORDERS_FULFILLMENT_SERVICE_FAILED_TO_COMPLETE", + "FULFILLMENT_ORDERS_HOLD_RELEASED", + "FULFILLMENT_ORDERS_LINE_ITEMS_PREPARED_FOR_LOCAL_DELIVERY", + "FULFILLMENT_ORDERS_LINE_ITEMS_PREPARED_FOR_PICKUP", + "FULFILLMENT_ORDERS_MOVED", + "FULFILLMENT_ORDERS_ORDER_ROUTING_COMPLETE", + "FULFILLMENT_ORDERS_PLACED_ON_HOLD", + "FULFILLMENT_ORDERS_RESCHEDULED", + "FULFILLMENT_ORDERS_SCHEDULED_FULFILLMENT_ORDER_READY", "INVENTORY_ITEMS_CREATE", "INVENTORY_ITEMS_DELETE", "INVENTORY_ITEMS_UPDATE", @@ -2937,7 +3806,9 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "INVENTORY_LEVELS_UPDATE", "LOCALES_CREATE", "LOCALES_UPDATE", + "LOCATIONS_ACTIVATE", "LOCATIONS_CREATE", + "LOCATIONS_DEACTIVATE", "LOCATIONS_DELETE", "LOCATIONS_UPDATE", "MARKETS_CREATE", @@ -2952,12 +3823,17 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "ORDERS_PARTIALLY_FULFILLED", "ORDERS_UPDATED", "ORDER_TRANSACTIONS_CREATE", + "PAYMENT_SCHEDULES_DUE", "PAYMENT_TERMS_CREATE", "PAYMENT_TERMS_DELETE", "PAYMENT_TERMS_UPDATE", "PRODUCTS_CREATE", "PRODUCTS_DELETE", "PRODUCTS_UPDATE", + "PRODUCT_FEEDS_CREATE", + "PRODUCT_FEEDS_FULL_SYNC", + "PRODUCT_FEEDS_INCREMENTAL_SYNC", + "PRODUCT_FEEDS_UPDATE", "PRODUCT_LISTINGS_ADD", "PRODUCT_LISTINGS_REMOVE", "PRODUCT_LISTINGS_UPDATE", @@ -2968,6 +3844,14 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "PROFILES_DELETE", "PROFILES_UPDATE", "REFUNDS_CREATE", + "RETURNS_APPROVE", + "RETURNS_CANCEL", + "RETURNS_CLOSE", + "RETURNS_DECLINE", + "RETURNS_REOPEN", + "RETURNS_REQUEST", + "REVERSE_DELIVERIES_ATTACH_DELIVERABLE", + "REVERSE_FULFILLMENT_ORDERS_DISPOSE", "SCHEDULED_PRODUCT_LISTINGS_ADD", "SCHEDULED_PRODUCT_LISTINGS_REMOVE", "SCHEDULED_PRODUCT_LISTINGS_UPDATE", @@ -2983,8 +3867,12 @@ class WebhookSubscriptionTopic(sgqlc.types.Enum): "SUBSCRIPTION_BILLING_ATTEMPTS_CHALLENGED", "SUBSCRIPTION_BILLING_ATTEMPTS_FAILURE", "SUBSCRIPTION_BILLING_ATTEMPTS_SUCCESS", + "SUBSCRIPTION_BILLING_CYCLE_EDITS_CREATE", + "SUBSCRIPTION_BILLING_CYCLE_EDITS_DELETE", + "SUBSCRIPTION_BILLING_CYCLE_EDITS_UPDATE", "SUBSCRIPTION_CONTRACTS_CREATE", "SUBSCRIPTION_CONTRACTS_UPDATE", + "TAX_PARTNERS_UPDATE", "TAX_SERVICES_CREATE", "TAX_SERVICES_UPDATE", "TENDER_TRANSACTIONS_CREATE", @@ -3066,26 +3954,52 @@ class AttributeInput(sgqlc.types.Input): class BuyerExperienceConfigurationInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("checkout_to_draft", "payment_terms_template_id") + __field_names__ = ("checkout_to_draft", "payment_terms_template_id", "editable_shipping_address") checkout_to_draft = sgqlc.types.Field(Boolean, graphql_name="checkoutToDraft") payment_terms_template_id = sgqlc.types.Field(ID, graphql_name="paymentTermsTemplateId") + editable_shipping_address = sgqlc.types.Field(Boolean, graphql_name="editableShippingAddress") -class CollectionDeleteInput(sgqlc.types.Input): +class CatalogContextInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id",) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + __field_names__ = ("company_location_ids",) + company_location_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="companyLocationIds") -class CollectionInput(sgqlc.types.Input): +class CatalogCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "description_html", - "handle", - "id", - "image", + __field_names__ = ("title", "status", "context", "price_list_id", "publication_id") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + status = sgqlc.types.Field(sgqlc.types.non_null(CatalogStatus), graphql_name="status") + context = sgqlc.types.Field(sgqlc.types.non_null(CatalogContextInput), graphql_name="context") + price_list_id = sgqlc.types.Field(ID, graphql_name="priceListId") + publication_id = sgqlc.types.Field(ID, graphql_name="publicationId") + + +class CatalogUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("title", "status", "context", "price_list_id", "publication_id") + title = sgqlc.types.Field(String, graphql_name="title") + status = sgqlc.types.Field(CatalogStatus, graphql_name="status") + context = sgqlc.types.Field(CatalogContextInput, graphql_name="context") + price_list_id = sgqlc.types.Field(ID, graphql_name="priceListId") + publication_id = sgqlc.types.Field(ID, graphql_name="publicationId") + + +class CollectionDeleteInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class CollectionInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ( + "description_html", + "handle", + "id", + "image", "products", - "private_metafields", "rule_set", "template_suffix", "sort_order", @@ -3099,9 +4013,6 @@ class CollectionInput(sgqlc.types.Input): id = sgqlc.types.Field(ID, graphql_name="id") image = sgqlc.types.Field("ImageInput", graphql_name="image") products = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="products") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("PrivateMetafieldInput")), graphql_name="privateMetafields" - ) rule_set = sgqlc.types.Field("CollectionRuleSetInput", graphql_name="ruleSet") template_suffix = sgqlc.types.Field(String, graphql_name="templateSuffix") sort_order = sgqlc.types.Field(CollectionSortOrder, graphql_name="sortOrder") @@ -3122,17 +4033,17 @@ class CollectionPublishInput(sgqlc.types.Input): __field_names__ = ("id", "collection_publications") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") collection_publications = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionPublicationInput))), - graphql_name="collectionPublications", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionPublicationInput))), graphql_name="collectionPublications" ) class CollectionRuleInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("column", "relation", "condition") + __field_names__ = ("column", "relation", "condition", "condition_object_id") column = sgqlc.types.Field(sgqlc.types.non_null(CollectionRuleColumn), graphql_name="column") relation = sgqlc.types.Field(sgqlc.types.non_null(CollectionRuleRelation), graphql_name="relation") condition = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="condition") + condition_object_id = sgqlc.types.Field(ID, graphql_name="conditionObjectId") class CollectionRuleSetInput(sgqlc.types.Input): @@ -3147,8 +4058,7 @@ class CollectionUnpublishInput(sgqlc.types.Input): __field_names__ = ("id", "collection_publications") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") collection_publications = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionPublicationInput))), - graphql_name="collectionPublications", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionPublicationInput))), graphql_name="collectionPublications" ) @@ -3253,6 +4163,13 @@ class ContextualPricingContext(sgqlc.types.Input): company_location_id = sgqlc.types.Field(ID, graphql_name="companyLocationId") +class ContextualPublicationContext(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("country", "company_location_id") + country = sgqlc.types.Field(CountryCode, graphql_name="country") + company_location_id = sgqlc.types.Field(ID, graphql_name="companyLocationId") + + class CountryHarmonizedSystemCodeInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("harmonized_system_code", "country_code") @@ -3268,6 +4185,16 @@ class CreateMediaInput(sgqlc.types.Input): media_content_type = sgqlc.types.Field(sgqlc.types.non_null(MediaContentType), graphql_name="mediaContentType") +class CustomShippingPackageInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("weight", "dimensions", "default", "name", "type") + weight = sgqlc.types.Field("WeightInput", graphql_name="weight") + dimensions = sgqlc.types.Field("ObjectDimensionsInput", graphql_name="dimensions") + default = sgqlc.types.Field(Boolean, graphql_name="default") + name = sgqlc.types.Field(String, graphql_name="name") + type = sgqlc.types.Field(ShippingPackageType, graphql_name="type") + + class CustomerDeleteInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("id",) @@ -3303,7 +4230,6 @@ class CustomerInput(sgqlc.types.Input): "metafields", "note", "phone", - "private_metafields", "tags", "email_marketing_consent", "sms_marketing_consent", @@ -3319,9 +4245,6 @@ class CustomerInput(sgqlc.types.Input): metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldInput")), graphql_name="metafields") note = sgqlc.types.Field(String, graphql_name="note") phone = sgqlc.types.Field(String, graphql_name="phone") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("PrivateMetafieldInput")), graphql_name="privateMetafields" - ) tags = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="tags") email_marketing_consent = sgqlc.types.Field(CustomerEmailMarketingConsentInput, graphql_name="emailMarketingConsent") sms_marketing_consent = sgqlc.types.Field("CustomerSmsMarketingConsentInput", graphql_name="smsMarketingConsent") @@ -3329,6 +4252,26 @@ class CustomerInput(sgqlc.types.Input): tax_exemptions = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(TaxExemption)), graphql_name="taxExemptions") +class CustomerMergeOverrideFields(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ( + "customer_id_of_first_name_to_keep", + "customer_id_of_last_name_to_keep", + "customer_id_of_email_to_keep", + "customer_id_of_phone_number_to_keep", + "customer_id_of_default_address_to_keep", + "note", + "tags", + ) + customer_id_of_first_name_to_keep = sgqlc.types.Field(ID, graphql_name="customerIdOfFirstNameToKeep") + customer_id_of_last_name_to_keep = sgqlc.types.Field(ID, graphql_name="customerIdOfLastNameToKeep") + customer_id_of_email_to_keep = sgqlc.types.Field(ID, graphql_name="customerIdOfEmailToKeep") + customer_id_of_phone_number_to_keep = sgqlc.types.Field(ID, graphql_name="customerIdOfPhoneNumberToKeep") + customer_id_of_default_address_to_keep = sgqlc.types.Field(ID, graphql_name="customerIdOfDefaultAddressToKeep") + note = sgqlc.types.Field(String, graphql_name="note") + tags = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="tags") + + class CustomerPaymentMethodRemoteInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("stripe_payment_method", "authorize_net_customer_payment_profile", "braintree_payment_method") @@ -3339,6 +4282,15 @@ class CustomerPaymentMethodRemoteInput(sgqlc.types.Input): braintree_payment_method = sgqlc.types.Field("RemoteBraintreePaymentMethodInput", graphql_name="braintreePaymentMethod") +class CustomerSegmentMembersQueryInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("segment_id", "query", "reverse", "sort_key") + segment_id = sgqlc.types.Field(ID, graphql_name="segmentId") + query = sgqlc.types.Field(String, graphql_name="query") + reverse = sgqlc.types.Field(Boolean, graphql_name="reverse") + sort_key = sgqlc.types.Field(String, graphql_name="sortKey") + + class CustomerSmsMarketingConsentInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("marketing_opt_in_level", "marketing_state", "consent_updated_at") @@ -3372,6 +4324,15 @@ class DeliveryCountryInput(sgqlc.types.Input): include_all_provinces = sgqlc.types.Field(Boolean, graphql_name="includeAllProvinces") +class DeliveryCustomizationInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("function_id", "title", "enabled", "metafields") + function_id = sgqlc.types.Field(String, graphql_name="functionId") + title = sgqlc.types.Field(String, graphql_name="title") + enabled = sgqlc.types.Field(Boolean, graphql_name="enabled") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldInput")), graphql_name="metafields") + + class DeliveryLocationGroupZoneInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("id", "name", "countries", "method_definitions_to_create", "method_definitions_to_update") @@ -3379,15 +4340,21 @@ class DeliveryLocationGroupZoneInput(sgqlc.types.Input): name = sgqlc.types.Field(String, graphql_name="name") countries = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryCountryInput)), graphql_name="countries") method_definitions_to_create = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionInput")), - graphql_name="methodDefinitionsToCreate", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionInput")), graphql_name="methodDefinitionsToCreate" ) method_definitions_to_update = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionInput")), - graphql_name="methodDefinitionsToUpdate", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionInput")), graphql_name="methodDefinitionsToUpdate" ) +class DeliveryLocationLocalPickupEnableInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("location_id", "pickup_time", "instructions") + location_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="locationId") + pickup_time = sgqlc.types.Field(sgqlc.types.non_null(DeliveryLocalPickupTime), graphql_name="pickupTime") + instructions = sgqlc.types.Field(String, graphql_name="instructions") + + class DeliveryMethodDefinitionInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ( @@ -3408,8 +4375,7 @@ class DeliveryMethodDefinitionInput(sgqlc.types.Input): rate_definition = sgqlc.types.Field("DeliveryRateDefinitionInput", graphql_name="rateDefinition") participant = sgqlc.types.Field("DeliveryParticipantInput", graphql_name="participant") weight_conditions_to_create = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryWeightConditionInput")), - graphql_name="weightConditionsToCreate", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryWeightConditionInput")), graphql_name="weightConditionsToCreate" ) price_conditions_to_create = sgqlc.types.Field( sgqlc.types.list_of(sgqlc.types.non_null("DeliveryPriceConditionInput")), graphql_name="priceConditionsToCreate" @@ -3421,14 +4387,7 @@ class DeliveryMethodDefinitionInput(sgqlc.types.Input): class DeliveryParticipantInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "id", - "carrier_service_id", - "fixed_fee", - "percentage_of_rate_fee", - "participant_services", - "adapt_to_new_services", - ) + __field_names__ = ("id", "carrier_service_id", "fixed_fee", "percentage_of_rate_fee", "participant_services", "adapt_to_new_services") id = sgqlc.types.Field(ID, graphql_name="id") carrier_service_id = sgqlc.types.Field(ID, graphql_name="carrierServiceId") fixed_fee = sgqlc.types.Field("MoneyInput", graphql_name="fixedFee") @@ -3471,16 +4430,13 @@ class DeliveryProfileInput(sgqlc.types.Input): ) name = sgqlc.types.Field(String, graphql_name="name") profile_location_groups = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), - graphql_name="profileLocationGroups", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), graphql_name="profileLocationGroups" ) location_groups_to_create = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), - graphql_name="locationGroupsToCreate", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), graphql_name="locationGroupsToCreate" ) location_groups_to_update = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), - graphql_name="locationGroupsToUpdate", + sgqlc.types.list_of(sgqlc.types.non_null("DeliveryProfileLocationGroupInput")), graphql_name="locationGroupsToUpdate" ) location_groups_to_delete = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationGroupsToDelete") variants_to_associate = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="variantsToAssociate") @@ -3500,9 +4456,11 @@ class DeliveryProfileInput(sgqlc.types.Input): class DeliveryProfileLocationGroupInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id", "locations", "zones_to_create", "zones_to_update") + __field_names__ = ("id", "locations", "locations_to_add", "locations_to_remove", "zones_to_create", "zones_to_update") id = sgqlc.types.Field(ID, graphql_name="id") locations = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locations") + locations_to_add = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationsToAdd") + locations_to_remove = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationsToRemove") zones_to_create = sgqlc.types.Field( sgqlc.types.list_of(sgqlc.types.non_null(DeliveryLocationGroupZoneInput)), graphql_name="zonesToCreate" ) @@ -3578,15 +4536,7 @@ class DiscountAutomaticBasicInput(sgqlc.types.Input): class DiscountAutomaticBxgyInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "combines_with", - "starts_at", - "ends_at", - "title", - "uses_per_order_limit", - "customer_buys", - "customer_gets", - ) + __field_names__ = ("combines_with", "starts_at", "ends_at", "title", "uses_per_order_limit", "customer_buys", "customer_gets") combines_with = sgqlc.types.Field("DiscountCombinesWithInput", graphql_name="combinesWith") starts_at = sgqlc.types.Field(DateTime, graphql_name="startsAt") ends_at = sgqlc.types.Field(DateTime, graphql_name="endsAt") @@ -3875,7 +4825,6 @@ class DraftOrderInput(sgqlc.types.Input): "email", "line_items", "metafields", - "private_metafields", "localization_extensions", "note", "shipping_address", @@ -3891,6 +4840,7 @@ class DraftOrderInput(sgqlc.types.Input): "payment_terms", "purchasing_entity", "source_name", + "po_number", ) applied_discount = sgqlc.types.Field(DraftOrderAppliedDiscountInput, graphql_name="appliedDiscount") billing_address = sgqlc.types.Field("MailingAddressInput", graphql_name="billingAddress") @@ -3898,9 +4848,6 @@ class DraftOrderInput(sgqlc.types.Input): email = sgqlc.types.Field(String, graphql_name="email") line_items = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("DraftOrderLineItemInput")), graphql_name="lineItems") metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldInput")), graphql_name="metafields") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null("PrivateMetafieldInput")), graphql_name="privateMetafields" - ) localization_extensions = sgqlc.types.Field( sgqlc.types.list_of(sgqlc.types.non_null("LocalizationExtensionInput")), graphql_name="localizationExtensions" ) @@ -3918,6 +4865,7 @@ class DraftOrderInput(sgqlc.types.Input): payment_terms = sgqlc.types.Field("PaymentTermsInput", graphql_name="paymentTerms") purchasing_entity = sgqlc.types.Field("PurchasingEntityInput", graphql_name="purchasingEntity") source_name = sgqlc.types.Field(String, graphql_name="sourceName") + po_number = sgqlc.types.Field(String, graphql_name="poNumber") class DraftOrderLineItemInput(sgqlc.types.Input): @@ -3968,26 +4916,64 @@ class EventBridgeWebhookSubscriptionInput(sgqlc.types.Input): class FileCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("original_source", "content_type", "alt") + __field_names__ = ("filename", "original_source", "content_type", "alt", "duplicate_resolution_mode") + filename = sgqlc.types.Field(String, graphql_name="filename") original_source = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="originalSource") content_type = sgqlc.types.Field(FileContentType, graphql_name="contentType") alt = sgqlc.types.Field(String, graphql_name="alt") + duplicate_resolution_mode = sgqlc.types.Field(FileCreateInputDuplicateResolutionMode, graphql_name="duplicateResolutionMode") class FileUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id", "alt", "preview_image_source") + __field_names__ = ("id", "alt", "original_source", "preview_image_source", "filename") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") alt = sgqlc.types.Field(String, graphql_name="alt") + original_source = sgqlc.types.Field(String, graphql_name="originalSource") preview_image_source = sgqlc.types.Field(String, graphql_name="previewImageSource") + filename = sgqlc.types.Field(String, graphql_name="filename") + + +class FulfillmentEventInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ( + "address1", + "city", + "country", + "estimated_delivery_at", + "happened_at", + "fulfillment_id", + "latitude", + "longitude", + "message", + "province", + "status", + "zip", + ) + address1 = sgqlc.types.Field(String, graphql_name="address1") + city = sgqlc.types.Field(String, graphql_name="city") + country = sgqlc.types.Field(String, graphql_name="country") + estimated_delivery_at = sgqlc.types.Field(DateTime, graphql_name="estimatedDeliveryAt") + happened_at = sgqlc.types.Field(DateTime, graphql_name="happenedAt") + fulfillment_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentId") + latitude = sgqlc.types.Field(Float, graphql_name="latitude") + longitude = sgqlc.types.Field(Float, graphql_name="longitude") + message = sgqlc.types.Field(String, graphql_name="message") + province = sgqlc.types.Field(String, graphql_name="province") + status = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentEventStatus), graphql_name="status") + zip = sgqlc.types.Field(String, graphql_name="zip") class FulfillmentOrderHoldInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("reason", "reason_notes", "notify_merchant") + __field_names__ = ("reason", "reason_notes", "notify_merchant", "external_id", "fulfillment_order_line_items") reason = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentHoldReason), graphql_name="reason") reason_notes = sgqlc.types.Field(String, graphql_name="reasonNotes") notify_merchant = sgqlc.types.Field(Boolean, graphql_name="notifyMerchant") + external_id = sgqlc.types.Field(String, graphql_name="externalId") + fulfillment_order_line_items = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItemInput")), graphql_name="fulfillmentOrderLineItems" + ) class FulfillmentOrderLineItemInput(sgqlc.types.Input): @@ -4002,9 +4988,45 @@ class FulfillmentOrderLineItemsInput(sgqlc.types.Input): __field_names__ = ("fulfillment_order_id", "fulfillment_order_line_items") fulfillment_order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentOrderId") fulfillment_order_line_items = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemInput)), + sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemInput)), graphql_name="fulfillmentOrderLineItems" + ) + + +class FulfillmentOrderLineItemsPreparedForPickupInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("line_items_by_fulfillment_order",) + line_items_by_fulfillment_order = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PreparedFulfillmentOrderLineItemsInput"))), + graphql_name="lineItemsByFulfillmentOrder", + ) + + +class FulfillmentOrderMergeInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("merge_intents",) + merge_intents = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMergeInputMergeIntent"))), + graphql_name="mergeIntents", + ) + + +class FulfillmentOrderMergeInputMergeIntent(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order_line_items", "fulfillment_order_id") + fulfillment_order_line_items = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemInput)), graphql_name="fulfillmentOrderLineItems" + ) + fulfillment_order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentOrderId") + + +class FulfillmentOrderSplitInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order_line_items", "fulfillment_order_id") + fulfillment_order_line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemInput))), graphql_name="fulfillmentOrderLineItems", ) + fulfillment_order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentOrderId") class FulfillmentOriginAddressInput(sgqlc.types.Input): @@ -4092,6 +5114,17 @@ class InventoryAdjustItemInput(sgqlc.types.Input): available_delta = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="availableDelta") +class InventoryAdjustQuantitiesInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reason", "name", "reference_document_uri", "changes") + reason = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="reason") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + reference_document_uri = sgqlc.types.Field(String, graphql_name="referenceDocumentUri") + changes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryChangeInput"))), graphql_name="changes" + ) + + class InventoryAdjustQuantityInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("inventory_level_id", "available_delta") @@ -4106,6 +5139,15 @@ class InventoryBulkToggleActivationInput(sgqlc.types.Input): activate = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="activate") +class InventoryChangeInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("delta", "inventory_item_id", "location_id", "ledger_document_uri") + delta = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="delta") + inventory_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="inventoryItemId") + location_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="locationId") + ledger_document_uri = sgqlc.types.Field(String, graphql_name="ledgerDocumentUri") + + class InventoryItemInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("cost", "tracked") @@ -4129,8 +5171,7 @@ class InventoryItemUpdateInput(sgqlc.types.Input): province_code_of_origin = sgqlc.types.Field(String, graphql_name="provinceCodeOfOrigin") harmonized_system_code = sgqlc.types.Field(String, graphql_name="harmonizedSystemCode") country_harmonized_system_codes = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(CountryHarmonizedSystemCodeInput)), - graphql_name="countryHarmonizedSystemCodes", + sgqlc.types.list_of(sgqlc.types.non_null(CountryHarmonizedSystemCodeInput)), graphql_name="countryHarmonizedSystemCodes" ) @@ -4141,6 +5182,51 @@ class InventoryLevelInput(sgqlc.types.Input): location_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="locationId") +class InventoryMoveQuantitiesInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reason", "reference_document_uri", "changes") + reason = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="reason") + reference_document_uri = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="referenceDocumentUri") + changes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryMoveQuantityChange"))), graphql_name="changes" + ) + + +class InventoryMoveQuantityChange(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("inventory_item_id", "quantity", "from_", "to") + inventory_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="inventoryItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + from_ = sgqlc.types.Field(sgqlc.types.non_null("InventoryMoveQuantityTerminalInput"), graphql_name="from") + to = sgqlc.types.Field(sgqlc.types.non_null("InventoryMoveQuantityTerminalInput"), graphql_name="to") + + +class InventoryMoveQuantityTerminalInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("location_id", "name", "ledger_document_uri") + location_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="locationId") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + ledger_document_uri = sgqlc.types.Field(String, graphql_name="ledgerDocumentUri") + + +class InventorySetOnHandQuantitiesInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reason", "reference_document_uri", "set_quantities") + reason = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="reason") + reference_document_uri = sgqlc.types.Field(String, graphql_name="referenceDocumentUri") + set_quantities = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventorySetQuantityInput"))), graphql_name="setQuantities" + ) + + +class InventorySetQuantityInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("inventory_item_id", "location_id", "quantity") + inventory_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="inventoryItemId") + location_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="locationId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + + class LocalizationExtensionInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("key", "value") @@ -4162,10 +5248,11 @@ class LocationAddAddressInput(sgqlc.types.Input): class LocationAddInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "address", "fulfills_online_orders") + __field_names__ = ("name", "address", "fulfills_online_orders", "metafields") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") address = sgqlc.types.Field(sgqlc.types.non_null(LocationAddAddressInput), graphql_name="address") fulfills_online_orders = sgqlc.types.Field(Boolean, graphql_name="fulfillsOnlineOrders") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldInput")), graphql_name="metafields") class LocationEditAddressInput(sgqlc.types.Input): @@ -4182,10 +5269,11 @@ class LocationEditAddressInput(sgqlc.types.Input): class LocationEditInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "address", "fulfills_online_orders") + __field_names__ = ("name", "address", "fulfills_online_orders", "metafields") name = sgqlc.types.Field(String, graphql_name="name") address = sgqlc.types.Field(LocationEditAddressInput, graphql_name="address") fulfills_online_orders = sgqlc.types.Field(Boolean, graphql_name="fulfillsOnlineOrders") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldInput")), graphql_name="metafields") class MailingAddressInput(sgqlc.types.Input): @@ -4216,12 +5304,12 @@ class MailingAddressInput(sgqlc.types.Input): class MarketCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "enabled", "regions") + __field_names__ = ("name", "handle", "enabled", "regions") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + handle = sgqlc.types.Field(String, graphql_name="handle") enabled = sgqlc.types.Field(Boolean, graphql_name="enabled") regions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketRegionCreateInput"))), - graphql_name="regions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketRegionCreateInput"))), graphql_name="regions" ) @@ -4249,8 +5337,9 @@ class MarketRegionCreateInput(sgqlc.types.Input): class MarketUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "enabled") + __field_names__ = ("name", "handle", "enabled") name = sgqlc.types.Field(String, graphql_name="name") + handle = sgqlc.types.Field(String, graphql_name="handle") enabled = sgqlc.types.Field(Boolean, graphql_name="enabled") @@ -4315,15 +5404,7 @@ class MarketingActivityCreateExternalInput(sgqlc.types.Input): class MarketingActivityCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "marketing_activity_title", - "form_data", - "marketing_activity_extension_id", - "context", - "utm", - "status", - "budget", - ) + __field_names__ = ("marketing_activity_title", "form_data", "marketing_activity_extension_id", "context", "utm", "status", "budget") marketing_activity_title = sgqlc.types.Field(String, graphql_name="marketingActivityTitle") form_data = sgqlc.types.Field(String, graphql_name="formData") marketing_activity_extension_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="marketingActivityExtensionId") @@ -4431,6 +5512,12 @@ class MarketingEngagementInput(sgqlc.types.Input): fetched_at = sgqlc.types.Field(DateTime, graphql_name="fetchedAt") +class MetafieldAccessInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("admin",) + admin = sgqlc.types.Field(sgqlc.types.non_null(MetafieldAdminAccess), graphql_name="admin") + + class MetafieldDefinitionInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ( @@ -4442,7 +5529,9 @@ class MetafieldDefinitionInput(sgqlc.types.Input): "type", "validations", "visible_to_storefront_api", + "use_as_collection_condition", "pin", + "access", ) namespace = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="namespace") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") @@ -4454,19 +5543,37 @@ class MetafieldDefinitionInput(sgqlc.types.Input): sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionValidationInput")), graphql_name="validations" ) visible_to_storefront_api = sgqlc.types.Field(Boolean, graphql_name="visibleToStorefrontApi") + use_as_collection_condition = sgqlc.types.Field(Boolean, graphql_name="useAsCollectionCondition") pin = sgqlc.types.Field(Boolean, graphql_name="pin") + access = sgqlc.types.Field(MetafieldAccessInput, graphql_name="access") class MetafieldDefinitionUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("namespace", "key", "name", "description", "owner_type", "pin", "visible_to_storefront_api") + __field_names__ = ( + "namespace", + "key", + "name", + "description", + "owner_type", + "validations", + "pin", + "visible_to_storefront_api", + "use_as_collection_condition", + "access", + ) namespace = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="namespace") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") name = sgqlc.types.Field(String, graphql_name="name") description = sgqlc.types.Field(String, graphql_name="description") owner_type = sgqlc.types.Field(sgqlc.types.non_null(MetafieldOwnerType), graphql_name="ownerType") + validations = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionValidationInput")), graphql_name="validations" + ) pin = sgqlc.types.Field(Boolean, graphql_name="pin") visible_to_storefront_api = sgqlc.types.Field(Boolean, graphql_name="visibleToStorefrontApi") + use_as_collection_condition = sgqlc.types.Field(Boolean, graphql_name="useAsCollectionCondition") + access = sgqlc.types.Field(MetafieldAccessInput, graphql_name="access") class MetafieldDefinitionValidationInput(sgqlc.types.Input): @@ -4484,8 +5591,7 @@ class MetafieldDeleteInput(sgqlc.types.Input): class MetafieldInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("description", "id", "namespace", "key", "value", "type") - description = sgqlc.types.Field(String, graphql_name="description") + __field_names__ = ("id", "namespace", "key", "value", "type") id = sgqlc.types.Field(ID, graphql_name="id") namespace = sgqlc.types.Field(String, graphql_name="namespace") key = sgqlc.types.Field(String, graphql_name="key") @@ -4508,97 +5614,276 @@ class MetafieldsSetInput(sgqlc.types.Input): namespace = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="namespace") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") value = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="value") - type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + type = sgqlc.types.Field(String, graphql_name="type") -class MoneyInput(sgqlc.types.Input): +class MetaobjectAccessInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("amount", "currency_code") - amount = sgqlc.types.Field(sgqlc.types.non_null(Decimal), graphql_name="amount") - currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") + __field_names__ = ("admin", "storefront") + admin = sgqlc.types.Field(MetaobjectAdminAccess, graphql_name="admin") + storefront = sgqlc.types.Field(MetaobjectStorefrontAccess, graphql_name="storefront") -class MoveInput(sgqlc.types.Input): +class MetaobjectBulkDeleteWhereCondition(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id", "new_position") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - new_position = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="newPosition") + __field_names__ = ("type", "ids") + type = sgqlc.types.Field(String, graphql_name="type") + ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids") -class OrderCaptureInput(sgqlc.types.Input): +class MetaobjectCapabilityCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id", "parent_transaction_id", "amount", "currency") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - parent_transaction_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="parentTransactionId") - amount = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="amount") - currency = sgqlc.types.Field(CurrencyCode, graphql_name="currency") + __field_names__ = ("publishable", "translatable") + publishable = sgqlc.types.Field("MetaobjectCapabilityPublishableInput", graphql_name="publishable") + translatable = sgqlc.types.Field("MetaobjectCapabilityTranslatableInput", graphql_name="translatable") -class OrderCloseInput(sgqlc.types.Input): +class MetaobjectCapabilityDataInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id",) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + __field_names__ = ("publishable",) + publishable = sgqlc.types.Field("MetaobjectCapabilityDataPublishableInput", graphql_name="publishable") -class OrderEditAppliedDiscountInput(sgqlc.types.Input): +class MetaobjectCapabilityDataPublishableInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("description", "fixed_value", "percent_value") - description = sgqlc.types.Field(String, graphql_name="description") - fixed_value = sgqlc.types.Field(MoneyInput, graphql_name="fixedValue") - percent_value = sgqlc.types.Field(Float, graphql_name="percentValue") + __field_names__ = ("status",) + status = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectStatus), graphql_name="status") -class OrderInput(sgqlc.types.Input): +class MetaobjectCapabilityPublishableInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "id", - "email", - "note", - "tags", - "shipping_address", - "custom_attributes", - "metafields", - "localization_extensions", - ) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - email = sgqlc.types.Field(String, graphql_name="email") - note = sgqlc.types.Field(String, graphql_name="note") - tags = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="tags") - shipping_address = sgqlc.types.Field(MailingAddressInput, graphql_name="shippingAddress") - custom_attributes = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(AttributeInput)), graphql_name="customAttributes") - metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") - localization_extensions = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(LocalizationExtensionInput)), graphql_name="localizationExtensions" - ) + __field_names__ = ("enabled",) + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") -class OrderMarkAsPaidInput(sgqlc.types.Input): +class MetaobjectCapabilityTranslatableInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id",) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + __field_names__ = ("enabled",) + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") -class OrderOpenInput(sgqlc.types.Input): +class MetaobjectCapabilityUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id",) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + __field_names__ = ("publishable", "translatable") + publishable = sgqlc.types.Field(MetaobjectCapabilityPublishableInput, graphql_name="publishable") + translatable = sgqlc.types.Field(MetaobjectCapabilityTranslatableInput, graphql_name="translatable") -class OrderTransactionInput(sgqlc.types.Input): +class MetaobjectCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("amount", "gateway", "kind", "order_id", "parent_id") - amount = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="amount") - gateway = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="gateway") - kind = sgqlc.types.Field(sgqlc.types.non_null(OrderTransactionKind), graphql_name="kind") - order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="orderId") - parent_id = sgqlc.types.Field(ID, graphql_name="parentId") + __field_names__ = ("type", "handle", "fields", "capabilities") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + handle = sgqlc.types.Field(String, graphql_name="handle") + fields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectFieldInput")), graphql_name="fields") + capabilities = sgqlc.types.Field(MetaobjectCapabilityDataInput, graphql_name="capabilities") -class PaymentScheduleInput(sgqlc.types.Input): +class MetaobjectDefinitionCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("issued_at", "due_at") - issued_at = sgqlc.types.Field(DateTime, graphql_name="issuedAt") - due_at = sgqlc.types.Field(DateTime, graphql_name="dueAt") + __field_names__ = ("name", "description", "type", "field_definitions", "access", "display_name_key", "capabilities") + name = sgqlc.types.Field(String, graphql_name="name") + description = sgqlc.types.Field(String, graphql_name="description") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + field_definitions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectFieldDefinitionCreateInput"))), + graphql_name="fieldDefinitions", + ) + access = sgqlc.types.Field(MetaobjectAccessInput, graphql_name="access") + display_name_key = sgqlc.types.Field(String, graphql_name="displayNameKey") + capabilities = sgqlc.types.Field(MetaobjectCapabilityCreateInput, graphql_name="capabilities") + + +class MetaobjectDefinitionUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("name", "description", "field_definitions", "access", "display_name_key", "reset_field_order", "capabilities") + name = sgqlc.types.Field(String, graphql_name="name") + description = sgqlc.types.Field(String, graphql_name="description") + field_definitions = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectFieldDefinitionOperationInput")), graphql_name="fieldDefinitions" + ) + access = sgqlc.types.Field(MetaobjectAccessInput, graphql_name="access") + display_name_key = sgqlc.types.Field(String, graphql_name="displayNameKey") + reset_field_order = sgqlc.types.Field(Boolean, graphql_name="resetFieldOrder") + capabilities = sgqlc.types.Field(MetaobjectCapabilityUpdateInput, graphql_name="capabilities") + + +class MetaobjectFieldDefinitionCreateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("key", "type", "name", "description", "required", "validations") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + name = sgqlc.types.Field(String, graphql_name="name") + description = sgqlc.types.Field(String, graphql_name="description") + required = sgqlc.types.Field(Boolean, graphql_name="required") + validations = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidationInput)), graphql_name="validations" + ) + + +class MetaobjectFieldDefinitionDeleteInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("key",) + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + + +class MetaobjectFieldDefinitionOperationInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("create", "update", "delete") + create = sgqlc.types.Field(MetaobjectFieldDefinitionCreateInput, graphql_name="create") + update = sgqlc.types.Field("MetaobjectFieldDefinitionUpdateInput", graphql_name="update") + delete = sgqlc.types.Field(MetaobjectFieldDefinitionDeleteInput, graphql_name="delete") + + +class MetaobjectFieldDefinitionUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("key", "name", "description", "required", "validations") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + name = sgqlc.types.Field(String, graphql_name="name") + description = sgqlc.types.Field(String, graphql_name="description") + required = sgqlc.types.Field(Boolean, graphql_name="required") + validations = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidationInput)), graphql_name="validations" + ) + + +class MetaobjectFieldInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("key", "value") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + value = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="value") + + +class MetaobjectHandleInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("type", "handle") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + + +class MetaobjectUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("handle", "fields", "capabilities") + handle = sgqlc.types.Field(String, graphql_name="handle") + fields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetaobjectFieldInput)), graphql_name="fields") + capabilities = sgqlc.types.Field(MetaobjectCapabilityDataInput, graphql_name="capabilities") + + +class MetaobjectUpsertInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("handle", "fields", "capabilities") + handle = sgqlc.types.Field(String, graphql_name="handle") + fields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetaobjectFieldInput)), graphql_name="fields") + capabilities = sgqlc.types.Field(MetaobjectCapabilityDataInput, graphql_name="capabilities") + + +class MoneyInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("amount", "currency_code") + amount = sgqlc.types.Field(sgqlc.types.non_null(Decimal), graphql_name="amount") + currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") + + +class MoveInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id", "new_position") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + new_position = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="newPosition") + + +class ObjectDimensionsInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("length", "width", "height", "unit") + length = sgqlc.types.Field(sgqlc.types.non_null(Float), graphql_name="length") + width = sgqlc.types.Field(sgqlc.types.non_null(Float), graphql_name="width") + height = sgqlc.types.Field(sgqlc.types.non_null(Float), graphql_name="height") + unit = sgqlc.types.Field(sgqlc.types.non_null(LengthUnit), graphql_name="unit") + + +class OrderCaptureInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id", "parent_transaction_id", "amount", "currency") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + parent_transaction_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="parentTransactionId") + amount = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="amount") + currency = sgqlc.types.Field(CurrencyCode, graphql_name="currency") + + +class OrderCloseInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class OrderEditAppliedDiscountInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("description", "fixed_value", "percent_value") + description = sgqlc.types.Field(String, graphql_name="description") + fixed_value = sgqlc.types.Field(MoneyInput, graphql_name="fixedValue") + percent_value = sgqlc.types.Field(Float, graphql_name="percentValue") + + +class OrderInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ( + "id", + "email", + "note", + "tags", + "shipping_address", + "custom_attributes", + "metafields", + "localization_extensions", + "po_number", + ) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + email = sgqlc.types.Field(String, graphql_name="email") + note = sgqlc.types.Field(String, graphql_name="note") + tags = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="tags") + shipping_address = sgqlc.types.Field(MailingAddressInput, graphql_name="shippingAddress") + custom_attributes = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(AttributeInput)), graphql_name="customAttributes") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") + localization_extensions = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(LocalizationExtensionInput)), graphql_name="localizationExtensions" + ) + po_number = sgqlc.types.Field(String, graphql_name="poNumber") + + +class OrderMarkAsPaidInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class OrderOpenInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class OrderTransactionInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("amount", "gateway", "kind", "order_id", "parent_id") + amount = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="amount") + gateway = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="gateway") + kind = sgqlc.types.Field(sgqlc.types.non_null(OrderTransactionKind), graphql_name="kind") + order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="orderId") + parent_id = sgqlc.types.Field(ID, graphql_name="parentId") + + +class PaymentCustomizationInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("function_id", "title", "enabled", "metafields") + function_id = sgqlc.types.Field(String, graphql_name="functionId") + title = sgqlc.types.Field(String, graphql_name="title") + enabled = sgqlc.types.Field(Boolean, graphql_name="enabled") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") + + +class PaymentScheduleInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("issued_at", "due_at") + issued_at = sgqlc.types.Field(DateTime, graphql_name="issuedAt") + due_at = sgqlc.types.Field(DateTime, graphql_name="dueAt") class PaymentTermsCreateInput(sgqlc.types.Input): @@ -4628,6 +5913,19 @@ class PaymentTermsUpdateInput(sgqlc.types.Input): payment_terms_attributes = sgqlc.types.Field(sgqlc.types.non_null(PaymentTermsInput), graphql_name="paymentTermsAttributes") +class PreparedFulfillmentOrderLineItemsInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order_id",) + fulfillment_order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentOrderId") + + +class PriceInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("calculation", "price") + calculation = sgqlc.types.Field(PriceCalculationType, graphql_name="calculation") + price = sgqlc.types.Field(Money, graphql_name="price") + + class PriceListAdjustmentInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("value", "type") @@ -4635,37 +5933,33 @@ class PriceListAdjustmentInput(sgqlc.types.Input): type = sgqlc.types.Field(sgqlc.types.non_null(PriceListAdjustmentType), graphql_name="type") -class PriceListContext(sgqlc.types.Input): - __schema__ = shopify_schema - __field_names__ = ("country",) - country = sgqlc.types.Field(CountryCode, graphql_name="country") - - -class PriceListContextRuleInput(sgqlc.types.Input): +class PriceListAdjustmentSettingsInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("market_id",) - market_id = sgqlc.types.Field(ID, graphql_name="marketId") + __field_names__ = ("compare_at_mode",) + compare_at_mode = sgqlc.types.Field(sgqlc.types.non_null(PriceListCompareAtMode), graphql_name="compareAtMode") class PriceListCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "currency", "parent", "context_rule") + __field_names__ = ("name", "currency", "parent", "catalog_id") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") currency = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currency") parent = sgqlc.types.Field(sgqlc.types.non_null("PriceListParentCreateInput"), graphql_name="parent") - context_rule = sgqlc.types.Field(PriceListContextRuleInput, graphql_name="contextRule") + catalog_id = sgqlc.types.Field(ID, graphql_name="catalogId") class PriceListParentCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("adjustment",) + __field_names__ = ("adjustment", "settings") adjustment = sgqlc.types.Field(sgqlc.types.non_null(PriceListAdjustmentInput), graphql_name="adjustment") + settings = sgqlc.types.Field(PriceListAdjustmentSettingsInput, graphql_name="settings") class PriceListParentUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("adjustment",) + __field_names__ = ("adjustment", "settings") adjustment = sgqlc.types.Field(sgqlc.types.non_null(PriceListAdjustmentInput), graphql_name="adjustment") + settings = sgqlc.types.Field(PriceListAdjustmentSettingsInput, graphql_name="settings") class PriceListPriceInput(sgqlc.types.Input): @@ -4676,13 +5970,20 @@ class PriceListPriceInput(sgqlc.types.Input): compare_at_price = sgqlc.types.Field(MoneyInput, graphql_name="compareAtPrice") +class PriceListProductPriceInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("product_id", "price") + product_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="productId") + price = sgqlc.types.Field(sgqlc.types.non_null(MoneyInput), graphql_name="price") + + class PriceListUpdateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("name", "currency", "context_rule", "parent") + __field_names__ = ("name", "currency", "parent", "catalog_id") name = sgqlc.types.Field(String, graphql_name="name") currency = sgqlc.types.Field(CurrencyCode, graphql_name="currency") - context_rule = sgqlc.types.Field(PriceListContextRuleInput, graphql_name="contextRule") parent = sgqlc.types.Field(PriceListParentUpdateInput, graphql_name="parent") + catalog_id = sgqlc.types.Field(ID, graphql_name="catalogId") class PriceRuleCustomerSelectionInput(sgqlc.types.Input): @@ -4856,6 +6157,22 @@ class ProductDeleteInput(sgqlc.types.Input): id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") +class ProductDuplicateAsyncInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("product_id", "new_title", "new_status", "include_images") + product_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="productId") + new_title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="newTitle") + new_status = sgqlc.types.Field(ProductStatus, graphql_name="newStatus") + include_images = sgqlc.types.Field(Boolean, graphql_name="includeImages") + + +class ProductFeedInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("language", "country") + language = sgqlc.types.Field(sgqlc.types.non_null(LanguageCode), graphql_name="language") + country = sgqlc.types.Field(sgqlc.types.non_null(CountryCode), graphql_name="country") + + class ProductInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ( @@ -4876,9 +6193,7 @@ class ProductInput(sgqlc.types.Input): "collections_to_join", "collections_to_leave", "id", - "images", "metafields", - "private_metafields", "options", "variants", "status", @@ -4901,11 +6216,7 @@ class ProductInput(sgqlc.types.Input): collections_to_join = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="collectionsToJoin") collections_to_leave = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="collectionsToLeave") id = sgqlc.types.Field(ID, graphql_name="id") - images = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ImageInput)), graphql_name="images") metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(PrivateMetafieldInput)), graphql_name="privateMetafields" - ) options = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="options") variants = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantInput")), graphql_name="variants") status = sgqlc.types.Field(ProductStatus, graphql_name="status") @@ -4924,8 +6235,7 @@ class ProductPublishInput(sgqlc.types.Input): __field_names__ = ("id", "product_publications") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") product_publications = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductPublicationInput))), - graphql_name="productPublications", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductPublicationInput))), graphql_name="productPublications" ) @@ -4944,8 +6254,7 @@ class ProductUnpublishInput(sgqlc.types.Input): __field_names__ = ("id", "product_publications") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") product_publications = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductPublicationInput))), - graphql_name="productPublications", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductPublicationInput))), graphql_name="productPublications" ) @@ -4963,21 +6272,27 @@ class ProductVariantDetachMediaInput(sgqlc.types.Input): media_ids = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="mediaIds") +class ProductVariantGroupRelationshipInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id", "quantity") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + + class ProductVariantInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ( + "requires_components", "barcode", "compare_at_price", "harmonized_system_code", "id", - "image_id", - "image_src", + "media_id", "media_src", "inventory_policy", "inventory_quantities", "inventory_item", "metafields", - "private_metafields", "options", "position", "price", @@ -4989,12 +6304,12 @@ class ProductVariantInput(sgqlc.types.Input): "weight", "weight_unit", ) + requires_components = sgqlc.types.Field(Boolean, graphql_name="requiresComponents") barcode = sgqlc.types.Field(String, graphql_name="barcode") compare_at_price = sgqlc.types.Field(Money, graphql_name="compareAtPrice") harmonized_system_code = sgqlc.types.Field(String, graphql_name="harmonizedSystemCode") id = sgqlc.types.Field(ID, graphql_name="id") - image_id = sgqlc.types.Field(ID, graphql_name="imageId") - image_src = sgqlc.types.Field(String, graphql_name="imageSrc") + media_id = sgqlc.types.Field(ID, graphql_name="mediaId") media_src = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="mediaSrc") inventory_policy = sgqlc.types.Field(ProductVariantInventoryPolicy, graphql_name="inventoryPolicy") inventory_quantities = sgqlc.types.Field( @@ -5002,9 +6317,6 @@ class ProductVariantInput(sgqlc.types.Input): ) inventory_item = sgqlc.types.Field(InventoryItemInput, graphql_name="inventoryItem") metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(PrivateMetafieldInput)), graphql_name="privateMetafields" - ) options = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="options") position = sgqlc.types.Field(Int, graphql_name="position") price = sgqlc.types.Field(Money, graphql_name="price") @@ -5024,6 +6336,32 @@ class ProductVariantPositionInput(sgqlc.types.Input): position = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="position") +class ProductVariantRelationshipUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ( + "parent_product_variant_id", + "parent_product_id", + "product_variant_relationships_to_create", + "product_variant_relationships_to_update", + "product_variant_relationships_to_remove", + "remove_all_product_variant_relationships", + "price_input", + ) + parent_product_variant_id = sgqlc.types.Field(ID, graphql_name="parentProductVariantId") + parent_product_id = sgqlc.types.Field(ID, graphql_name="parentProductId") + product_variant_relationships_to_create = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(ProductVariantGroupRelationshipInput)), graphql_name="productVariantRelationshipsToCreate" + ) + product_variant_relationships_to_update = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(ProductVariantGroupRelationshipInput)), graphql_name="productVariantRelationshipsToUpdate" + ) + product_variant_relationships_to_remove = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="productVariantRelationshipsToRemove" + ) + remove_all_product_variant_relationships = sgqlc.types.Field(Boolean, graphql_name="removeAllProductVariantRelationships") + price_input = sgqlc.types.Field(PriceInput, graphql_name="priceInput") + + class ProductVariantsBulkInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ( @@ -5031,14 +6369,12 @@ class ProductVariantsBulkInput(sgqlc.types.Input): "compare_at_price", "harmonized_system_code", "id", - "image_id", - "image_src", "media_src", "inventory_policy", "inventory_quantities", "inventory_item", + "media_id", "metafields", - "private_metafields", "options", "price", "requires_shipping", @@ -5052,18 +6388,14 @@ class ProductVariantsBulkInput(sgqlc.types.Input): compare_at_price = sgqlc.types.Field(Money, graphql_name="compareAtPrice") harmonized_system_code = sgqlc.types.Field(String, graphql_name="harmonizedSystemCode") id = sgqlc.types.Field(ID, graphql_name="id") - image_id = sgqlc.types.Field(ID, graphql_name="imageId") - image_src = sgqlc.types.Field(String, graphql_name="imageSrc") media_src = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="mediaSrc") inventory_policy = sgqlc.types.Field(ProductVariantInventoryPolicy, graphql_name="inventoryPolicy") inventory_quantities = sgqlc.types.Field( sgqlc.types.list_of(sgqlc.types.non_null(InventoryLevelInput)), graphql_name="inventoryQuantities" ) inventory_item = sgqlc.types.Field(InventoryItemInput, graphql_name="inventoryItem") + media_id = sgqlc.types.Field(ID, graphql_name="mediaId") metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldInput)), graphql_name="metafields") - private_metafields = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(PrivateMetafieldInput)), graphql_name="privateMetafields" - ) options = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="options") price = sgqlc.types.Field(Money, graphql_name="price") requires_shipping = sgqlc.types.Field(Boolean, graphql_name="requiresShipping") @@ -5084,6 +6416,14 @@ class PubSubWebhookSubscriptionInput(sgqlc.types.Input): metafield_namespaces = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="metafieldNamespaces") +class PublicationCreateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("catalog_id", "default_state", "auto_publish") + catalog_id = sgqlc.types.Field(ID, graphql_name="catalogId") + default_state = sgqlc.types.Field(PublicationCreateInputPublicationDefaultState, graphql_name="defaultState") + auto_publish = sgqlc.types.Field(Boolean, graphql_name="autoPublish") + + class PublicationInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("publication_id", "publish_date") @@ -5091,6 +6431,14 @@ class PublicationInput(sgqlc.types.Input): publish_date = sgqlc.types.Field(DateTime, graphql_name="publishDate") +class PublicationUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("publishables_to_add", "publishables_to_remove", "auto_publish") + publishables_to_add = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="publishablesToAdd") + publishables_to_remove = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="publishablesToRemove") + auto_publish = sgqlc.types.Field(Boolean, graphql_name="autoPublish") + + class PurchasingCompanyInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("company_id", "company_contact_id", "company_location_id") @@ -5106,6 +6454,15 @@ class PurchasingEntityInput(sgqlc.types.Input): purchasing_company = sgqlc.types.Field(PurchasingCompanyInput, graphql_name="purchasingCompany") +class QuantityRuleInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("increment", "maximum", "minimum", "variant_id") + increment = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="increment") + maximum = sgqlc.types.Field(Int, graphql_name="maximum") + minimum = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="minimum") + variant_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="variantId") + + class RefundDutyInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("duty_id", "refund_type") @@ -5115,16 +6472,7 @@ class RefundDutyInput(sgqlc.types.Input): class RefundInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "currency", - "order_id", - "note", - "notify", - "shipping", - "refund_line_items", - "refund_duties", - "transactions", - ) + __field_names__ = ("currency", "order_id", "note", "notify", "shipping", "refund_line_items", "refund_duties", "transactions") currency = sgqlc.types.Field(CurrencyCode, graphql_name="currency") order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="orderId") note = sgqlc.types.Field(String, graphql_name="note") @@ -5144,6 +6492,13 @@ class RefundLineItemInput(sgqlc.types.Input): location_id = sgqlc.types.Field(ID, graphql_name="locationId") +class RefundShippingInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("shipping_refund_amount", "full_refund") + shipping_refund_amount = sgqlc.types.Field(MoneyInput, graphql_name="shippingRefundAmount") + full_refund = sgqlc.types.Field(Boolean, graphql_name="fullRefund") + + class RemoteAuthorizeNetCustomerPaymentProfileInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("customer_profile_id", "customer_payment_profile_id") @@ -5165,55 +6520,181 @@ class RemoteStripePaymentMethodInput(sgqlc.types.Input): payment_method_id = sgqlc.types.Field(String, graphql_name="paymentMethodId") -class SEOInput(sgqlc.types.Input): - __schema__ = shopify_schema - __field_names__ = ("title", "description") - title = sgqlc.types.Field(String, graphql_name="title") - description = sgqlc.types.Field(String, graphql_name="description") - - -class SavedSearchCreateInput(sgqlc.types.Input): +class ResourceFeedbackCreateInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("resource_type", "name", "query") - resource_type = sgqlc.types.Field(sgqlc.types.non_null(SearchResultType), graphql_name="resourceType") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - query = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="query") + __field_names__ = ("feedback_generated_at", "messages", "state") + feedback_generated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="feedbackGeneratedAt") + messages = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="messages") + state = sgqlc.types.Field(sgqlc.types.non_null(ResourceFeedbackState), graphql_name="state") -class SavedSearchDeleteInput(sgqlc.types.Input): +class ReturnApproveRequestInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("id",) id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") -class SavedSearchUpdateInput(sgqlc.types.Input): +class ReturnDeclineRequestInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("id", "name", "query") + __field_names__ = ("id", "decline_reason") id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - name = sgqlc.types.Field(String, graphql_name="name") - query = sgqlc.types.Field(String, graphql_name="query") + decline_reason = sgqlc.types.Field(sgqlc.types.non_null(ReturnDeclineReason), graphql_name="declineReason") -class ScriptTagInput(sgqlc.types.Input): +class ReturnInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("src", "display_scope", "cache") - src = sgqlc.types.Field(URL, graphql_name="src") - display_scope = sgqlc.types.Field(ScriptTagDisplayScope, graphql_name="displayScope") - cache = sgqlc.types.Field(Boolean, graphql_name="cache") + __field_names__ = ("order_id", "return_line_items", "notify_customer", "requested_at") + order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="orderId") + return_line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnLineItemInput"))), graphql_name="returnLineItems" + ) + notify_customer = sgqlc.types.Field(Boolean, graphql_name="notifyCustomer") + requested_at = sgqlc.types.Field(DateTime, graphql_name="requestedAt") -class SellingPlanAnchorInput(sgqlc.types.Input): +class ReturnLineItemInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("type", "day", "month", "cutoff_day") - type = sgqlc.types.Field(SellingPlanAnchorType, graphql_name="type") - day = sgqlc.types.Field(Int, graphql_name="day") - month = sgqlc.types.Field(Int, graphql_name="month") - cutoff_day = sgqlc.types.Field(Int, graphql_name="cutoffDay") + __field_names__ = ("fulfillment_line_item_id", "quantity", "return_reason", "return_reason_note") + fulfillment_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + return_reason = sgqlc.types.Field(sgqlc.types.non_null(ReturnReason), graphql_name="returnReason") + return_reason_note = sgqlc.types.Field(String, graphql_name="returnReasonNote") -class SellingPlanBillingPolicyInput(sgqlc.types.Input): +class ReturnRefundInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ("fixed", "recurring") + __field_names__ = ("return_id", "return_refund_line_items", "refund_shipping", "refund_duties", "order_transactions", "notify_customer") + return_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="returnId") + return_refund_line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnRefundLineItemInput"))), graphql_name="returnRefundLineItems" + ) + refund_shipping = sgqlc.types.Field(RefundShippingInput, graphql_name="refundShipping") + refund_duties = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(RefundDutyInput)), graphql_name="refundDuties") + order_transactions = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("ReturnRefundOrderTransactionInput")), graphql_name="orderTransactions" + ) + notify_customer = sgqlc.types.Field(Boolean, graphql_name="notifyCustomer") + + +class ReturnRefundLineItemInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("return_line_item_id", "quantity") + return_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="returnLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + + +class ReturnRefundOrderTransactionInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("transaction_amount", "parent_id") + transaction_amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyInput), graphql_name="transactionAmount") + parent_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="parentId") + + +class ReturnRequestInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("order_id", "return_line_items") + order_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="orderId") + return_line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnRequestLineItemInput"))), graphql_name="returnLineItems" + ) + + +class ReturnRequestLineItemInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_line_item_id", "quantity", "return_reason", "customer_note") + fulfillment_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="fulfillmentLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + return_reason = sgqlc.types.Field(sgqlc.types.non_null(ReturnReason), graphql_name="returnReason") + customer_note = sgqlc.types.Field(String, graphql_name="customerNote") + + +class ReverseDeliveryDisposeInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reverse_delivery_line_item_id", "quantity", "disposition_type", "location_id") + reverse_delivery_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="reverseDeliveryLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + disposition_type = sgqlc.types.Field(sgqlc.types.non_null(ReverseFulfillmentOrderDispositionType), graphql_name="dispositionType") + location_id = sgqlc.types.Field(ID, graphql_name="locationId") + + +class ReverseDeliveryLabelInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("file_url",) + file_url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="fileUrl") + + +class ReverseDeliveryLineItemInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reverse_fulfillment_order_line_item_id", "quantity") + reverse_fulfillment_order_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="reverseFulfillmentOrderLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + + +class ReverseDeliveryTrackingInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("number", "url") + number = sgqlc.types.Field(String, graphql_name="number") + url = sgqlc.types.Field(URL, graphql_name="url") + + +class ReverseFulfillmentOrderDisposeInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("reverse_fulfillment_order_line_item_id", "quantity", "location_id", "disposition_type") + reverse_fulfillment_order_line_item_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="reverseFulfillmentOrderLineItemId") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + location_id = sgqlc.types.Field(ID, graphql_name="locationId") + disposition_type = sgqlc.types.Field(sgqlc.types.non_null(ReverseFulfillmentOrderDispositionType), graphql_name="dispositionType") + + +class SEOInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("title", "description") + title = sgqlc.types.Field(String, graphql_name="title") + description = sgqlc.types.Field(String, graphql_name="description") + + +class SavedSearchCreateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("resource_type", "name", "query") + resource_type = sgqlc.types.Field(sgqlc.types.non_null(SearchResultType), graphql_name="resourceType") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + query = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="query") + + +class SavedSearchDeleteInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class SavedSearchUpdateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("id", "name", "query") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + name = sgqlc.types.Field(String, graphql_name="name") + query = sgqlc.types.Field(String, graphql_name="query") + + +class ScriptTagInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("src", "display_scope", "cache") + src = sgqlc.types.Field(URL, graphql_name="src") + display_scope = sgqlc.types.Field(ScriptTagDisplayScope, graphql_name="displayScope") + cache = sgqlc.types.Field(Boolean, graphql_name="cache") + + +class SellingPlanAnchorInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("type", "day", "month", "cutoff_day") + type = sgqlc.types.Field(SellingPlanAnchorType, graphql_name="type") + day = sgqlc.types.Field(Int, graphql_name="day") + month = sgqlc.types.Field(Int, graphql_name="month") + cutoff_day = sgqlc.types.Field(Int, graphql_name="cutoffDay") + + +class SellingPlanBillingPolicyInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("fixed", "recurring") fixed = sgqlc.types.Field("SellingPlanFixedBillingPolicyInput", graphql_name="fixed") recurring = sgqlc.types.Field("SellingPlanRecurringBillingPolicyInput", graphql_name="recurring") @@ -5257,14 +6738,7 @@ class SellingPlanFixedBillingPolicyInput(sgqlc.types.Input): class SellingPlanFixedDeliveryPolicyInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "anchors", - "fulfillment_trigger", - "fulfillment_exact_time", - "cutoff", - "intent", - "pre_anchor_behavior", - ) + __field_names__ = ("anchors", "fulfillment_trigger", "fulfillment_exact_time", "cutoff", "intent", "pre_anchor_behavior") anchors = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(SellingPlanAnchorInput)), graphql_name="anchors") fulfillment_trigger = sgqlc.types.Field(SellingPlanFulfillmentTrigger, graphql_name="fulfillmentTrigger") fulfillment_exact_time = sgqlc.types.Field(DateTime, graphql_name="fulfillmentExactTime") @@ -5517,6 +6991,23 @@ class StorefrontAccessTokenInput(sgqlc.types.Input): title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") +class SubscriptionAtomicLineInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("line", "discounts") + line = sgqlc.types.Field(sgqlc.types.non_null("SubscriptionLineInput"), graphql_name="line") + discounts = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionAtomicManualDiscountInput")), graphql_name="discounts" + ) + + +class SubscriptionAtomicManualDiscountInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("title", "value", "recurring_cycle_limit") + title = sgqlc.types.Field(String, graphql_name="title") + value = sgqlc.types.Field("SubscriptionManualDiscountValueInput", graphql_name="value") + recurring_cycle_limit = sgqlc.types.Field(Int, graphql_name="recurringCycleLimit") + + class SubscriptionBillingAttemptInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("idempotency_key", "origin_time", "billing_cycle_selector") @@ -5571,6 +7062,19 @@ class SubscriptionBillingPolicyInput(sgqlc.types.Input): anchors = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(SellingPlanAnchorInput)), graphql_name="anchors") +class SubscriptionContractAtomicCreateInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("customer_id", "next_billing_date", "currency_code", "contract", "lines", "discount_codes") + customer_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="customerId") + next_billing_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="nextBillingDate") + currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") + contract = sgqlc.types.Field(sgqlc.types.non_null("SubscriptionDraftInput"), graphql_name="contract") + lines = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionAtomicLineInput))), graphql_name="lines" + ) + discount_codes = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="discountCodes") + + class SubscriptionContractCreateInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("customer_id", "next_billing_date", "currency_code", "contract") @@ -5580,6 +7084,13 @@ class SubscriptionContractCreateInput(sgqlc.types.Input): contract = sgqlc.types.Field(sgqlc.types.non_null("SubscriptionDraftInput"), graphql_name="contract") +class SubscriptionContractProductChangeInput(sgqlc.types.Input): + __schema__ = shopify_schema + __field_names__ = ("product_variant_id", "current_price") + product_variant_id = sgqlc.types.Field(ID, graphql_name="productVariantId") + current_price = sgqlc.types.Field(Decimal, graphql_name="currentPrice") + + class SubscriptionDeliveryMethodInput(sgqlc.types.Input): __schema__ = shopify_schema __field_names__ = ("shipping", "local_delivery", "pickup") @@ -5815,20 +7326,11 @@ class WebPixelInput(sgqlc.types.Input): class WebhookSubscriptionInput(sgqlc.types.Input): __schema__ = shopify_schema - __field_names__ = ( - "callback_url", - "format", - "include_fields", - "metafield_namespaces", - "private_metafield_namespaces", - ) + __field_names__ = ("callback_url", "format", "include_fields", "metafield_namespaces") callback_url = sgqlc.types.Field(URL, graphql_name="callbackUrl") format = sgqlc.types.Field(WebhookSubscriptionFormat, graphql_name="format") include_fields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="includeFields") metafield_namespaces = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="metafieldNamespaces") - private_metafield_namespaces = sgqlc.types.Field( - sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="privateMetafieldNamespaces" - ) class WeightInput(sgqlc.types.Input): @@ -5841,103 +7343,594 @@ class WeightInput(sgqlc.types.Input): ######################################################################## # Output Objects and Interfaces ######################################################################## -class AccessScope(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("description", "handle") - description = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="description") - handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") - - -class AllDiscountItems(sgqlc.types.Type): +class AppPurchase(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("all_items",) - all_items = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="allItems") + __field_names__ = ("created_at", "name", "price", "status", "test") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + price = sgqlc.types.Field(sgqlc.types.non_null("MoneyV2"), graphql_name="price") + status = sgqlc.types.Field(sgqlc.types.non_null(AppPurchaseStatus), graphql_name="status") + test = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="test") -class ApiVersion(sgqlc.types.Type): +class CalculatedDiscountApplication(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("display_name", "handle", "supported") - display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") - handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") - supported = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supported") + __field_names__ = ("allocation_method", "applied_to", "description", "id", "target_selection", "target_type", "value") + allocation_method = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationAllocationMethod), graphql_name="allocationMethod") + applied_to = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationLevel), graphql_name="appliedTo") + description = sgqlc.types.Field(String, graphql_name="description") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + target_selection = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetSelection), graphql_name="targetSelection") + target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") + value = sgqlc.types.Field(sgqlc.types.non_null("PricingValue"), graphql_name="value") -class AppConnection(sgqlc.types.relay.Connection): +class CommentEventSubject(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("App"))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + __field_names__ = ("has_timeline_comment", "id") + has_timeline_comment = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="hasTimelineComment") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") -class AppCreditConnection(sgqlc.types.relay.Connection): +class CustomerMoment(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppCreditEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppCredit"))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + __field_names__ = ("occurred_at",) + occurred_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="occurredAt") -class AppCreditCreatePayload(sgqlc.types.Type): +class DiscountApplication(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("app_credit", "user_errors") - app_credit = sgqlc.types.Field("AppCredit", graphql_name="appCredit") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + __field_names__ = ("allocation_method", "index", "target_selection", "target_type", "value") + allocation_method = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationAllocationMethod), graphql_name="allocationMethod") + index = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="index") + target_selection = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetSelection), graphql_name="targetSelection") + target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") + value = sgqlc.types.Field(sgqlc.types.non_null("PricingValue"), graphql_name="value") -class AppCreditEdge(sgqlc.types.Type): +class DisplayableError(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("AppCredit"), graphql_name="node") + __field_names__ = ("field", "message") + field = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="field") + message = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="message") -class AppDiscountType(sgqlc.types.Type): +class Event(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ( - "app", - "app_bridge", - "app_key", - "description", - "discount_class", - "function_id", - "target_type", - "title", - ) - app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") - app_bridge = sgqlc.types.Field(sgqlc.types.non_null("FunctionsAppBridge"), graphql_name="appBridge") - app_key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="appKey") - description = sgqlc.types.Field(String, graphql_name="description") - discount_class = sgqlc.types.Field(sgqlc.types.non_null(DiscountClass), graphql_name="discountClass") - function_id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="functionId") - target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") - title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + __field_names__ = ("app_title", "attribute_to_app", "attribute_to_user", "created_at", "critical_alert", "id", "message") + app_title = sgqlc.types.Field(String, graphql_name="appTitle") + attribute_to_app = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="attributeToApp") + attribute_to_user = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="attributeToUser") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + critical_alert = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="criticalAlert") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + message = sgqlc.types.Field(sgqlc.types.non_null(FormattedString), graphql_name="message") -class AppEdge(sgqlc.types.Type): +class File(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="node") + __field_names__ = ("alt", "created_at", "file_errors", "file_status", "id", "preview", "updated_at") + alt = sgqlc.types.Field(String, graphql_name="alt") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + file_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FileError"))), graphql_name="fileErrors") + file_status = sgqlc.types.Field(sgqlc.types.non_null(FileStatus), graphql_name="fileStatus") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + preview = sgqlc.types.Field("MediaPreviewImage", graphql_name="preview") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") -class AppFeedback(sgqlc.types.Type): +class HasEvents(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("app", "link", "messages") - app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") - link = sgqlc.types.Field("Link", graphql_name="link") - messages = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="messages") + __field_names__ = ("events",) + events = sgqlc.types.Field( + sgqlc.types.non_null("EventConnection"), + graphql_name="events", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(EventSortKeys, graphql_name="sortKey", default="ID")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) -class AppInstallationConnection(sgqlc.types.relay.Connection): +class HasLocalizationExtensions(sgqlc.types.Interface): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppInstallationEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppInstallation"))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") - - -class AppInstallationEdge(sgqlc.types.Type): + __field_names__ = ("localization_extensions",) + localization_extensions = sgqlc.types.Field( + sgqlc.types.non_null("LocalizationExtensionConnection"), + graphql_name="localizationExtensions", + args=sgqlc.types.ArgDict( + ( + ( + "country_codes", + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CountryCode)), graphql_name="countryCodes", default=None), + ), + ( + "purposes", + sgqlc.types.Arg( + sgqlc.types.list_of(sgqlc.types.non_null(LocalizationExtensionPurpose)), graphql_name="purposes", default=None + ), + ), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + +class HasMetafieldDefinitions(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("metafield_definitions",) + metafield_definitions = sgqlc.types.Field( + sgqlc.types.non_null("MetafieldDefinitionConnection"), + graphql_name="metafieldDefinitions", + args=sgqlc.types.ArgDict( + ( + ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), + ("pinned_status", sgqlc.types.Arg(MetafieldDefinitionPinnedStatus, graphql_name="pinnedStatus", default="ANY")), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(MetafieldDefinitionSortKeys, graphql_name="sortKey", default="ID")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) + + +class HasMetafields(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("metafield", "metafields") + metafield = sgqlc.types.Field( + "Metafield", + graphql_name="metafield", + args=sgqlc.types.ArgDict( + ( + ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), + ("key", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="key", default=None)), + ) + ), + ) + metafields = sgqlc.types.Field( + sgqlc.types.non_null("MetafieldConnection"), + graphql_name="metafields", + args=sgqlc.types.ArgDict( + ( + ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), + ("keys", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="keys", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + +class HasPublishedTranslations(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("translations",) + translations = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Translation"))), + graphql_name="translations", + args=sgqlc.types.ArgDict( + ( + ("locale", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="locale", default=None)), + ("market_id", sgqlc.types.Arg(ID, graphql_name="marketId", default=None)), + ) + ), + ) + + +class JobResult(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("done", "id") + done = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="done") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class LegacyInteroperability(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("legacy_resource_id",) + legacy_resource_id = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="legacyResourceId") + + +class MarketRegion(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("id", "name") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + + +class Media(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("alt", "id", "media_content_type", "media_errors", "media_warnings", "preview", "status") + alt = sgqlc.types.Field(String, graphql_name="alt") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + media_content_type = sgqlc.types.Field(sgqlc.types.non_null(MediaContentType), graphql_name="mediaContentType") + media_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaError"))), graphql_name="mediaErrors" + ) + media_warnings = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaWarning"))), graphql_name="mediaWarnings" + ) + preview = sgqlc.types.Field("MediaPreviewImage", graphql_name="preview") + status = sgqlc.types.Field(sgqlc.types.non_null(MediaStatus), graphql_name="status") + + +class Navigable(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("default_cursor",) + default_cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="defaultCursor") + + +class Node(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("id",) + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + +class OnlineStorePreviewable(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("online_store_preview_url",) + online_store_preview_url = sgqlc.types.Field(URL, graphql_name="onlineStorePreviewUrl") + + +class Publishable(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ( + "available_publication_count", + "publication_count", + "published_on_current_publication", + "published_on_publication", + "resource_publications", + "resource_publications_v2", + "unpublished_publications", + ) + available_publication_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="availablePublicationCount") + publication_count = sgqlc.types.Field( + sgqlc.types.non_null(Int), + graphql_name="publicationCount", + args=sgqlc.types.ArgDict((("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)),)), + ) + published_on_current_publication = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="publishedOnCurrentPublication") + published_on_publication = sgqlc.types.Field( + sgqlc.types.non_null(Boolean), + graphql_name="publishedOnPublication", + args=sgqlc.types.ArgDict( + (("publication_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="publicationId", default=None)),) + ), + ) + resource_publications = sgqlc.types.Field( + sgqlc.types.non_null("ResourcePublicationConnection"), + graphql_name="resourcePublications", + args=sgqlc.types.ArgDict( + ( + ("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + resource_publications_v2 = sgqlc.types.Field( + sgqlc.types.non_null("ResourcePublicationV2Connection"), + graphql_name="resourcePublicationsV2", + args=sgqlc.types.ArgDict( + ( + ("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)), + ("catalog_type", sgqlc.types.Arg(CatalogType, graphql_name="catalogType", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + unpublished_publications = sgqlc.types.Field( + sgqlc.types.non_null("PublicationConnection"), + graphql_name="unpublishedPublications", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + +class ResourceOperation(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("id", "processed_row_count", "row_count", "status") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + processed_row_count = sgqlc.types.Field(Int, graphql_name="processedRowCount") + row_count = sgqlc.types.Field("RowCount", graphql_name="rowCount") + status = sgqlc.types.Field(sgqlc.types.non_null(ResourceOperationStatus), graphql_name="status") + + +class Sale(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ( + "action_type", + "id", + "line_type", + "quantity", + "taxes", + "total_amount", + "total_discount_amount_after_taxes", + "total_discount_amount_before_taxes", + "total_tax_amount", + ) + action_type = sgqlc.types.Field(sgqlc.types.non_null(SaleActionType), graphql_name="actionType") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + line_type = sgqlc.types.Field(sgqlc.types.non_null(SaleLineType), graphql_name="lineType") + quantity = sgqlc.types.Field(Int, graphql_name="quantity") + taxes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SaleTax"))), graphql_name="taxes") + total_amount = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalAmount") + total_discount_amount_after_taxes = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalDiscountAmountAfterTaxes") + total_discount_amount_before_taxes = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalDiscountAmountBeforeTaxes") + total_tax_amount = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalTaxAmount") + + +class SalesAgreement(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("app", "happened_at", "id", "reason", "sales", "user") + app = sgqlc.types.Field("App", graphql_name="app") + happened_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="happenedAt") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + reason = sgqlc.types.Field(sgqlc.types.non_null(OrderActionType), graphql_name="reason") + sales = sgqlc.types.Field( + sgqlc.types.non_null("SaleConnection"), + graphql_name="sales", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + user = sgqlc.types.Field("StaffMember", graphql_name="user") + + +class SegmentFilter(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("localized_name", "multi_value", "query_name") + localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") + multi_value = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="multiValue") + query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") + + +class SellingPlanPricingPolicyBase(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("adjustment_type", "adjustment_value") + adjustment_type = sgqlc.types.Field(sgqlc.types.non_null(SellingPlanPricingPolicyAdjustmentType), graphql_name="adjustmentType") + adjustment_value = sgqlc.types.Field(sgqlc.types.non_null("SellingPlanPricingPolicyAdjustmentValue"), graphql_name="adjustmentValue") + + +class ShopifyPaymentsChargeStatementDescriptor(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("default", "prefix") + default = sgqlc.types.Field(String, graphql_name="default") + prefix = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="prefix") + + +class ShopifyqlResponse(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("parse_errors", "table_data") + parse_errors = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("ParseError")), graphql_name="parseErrors") + table_data = sgqlc.types.Field("TableData", graphql_name="tableData") + + +class SubscriptionContractBase(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ( + "app", + "app_admin_url", + "currency_code", + "custom_attributes", + "customer", + "customer_payment_method", + "delivery_method", + "delivery_price", + "discounts", + "line_count", + "lines", + "note", + "orders", + "updated_at", + ) + app = sgqlc.types.Field("App", graphql_name="app") + app_admin_url = sgqlc.types.Field(URL, graphql_name="appAdminUrl") + currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") + custom_attributes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Attribute"))), graphql_name="customAttributes" + ) + customer = sgqlc.types.Field("Customer", graphql_name="customer") + customer_payment_method = sgqlc.types.Field( + "CustomerPaymentMethod", + graphql_name="customerPaymentMethod", + args=sgqlc.types.ArgDict((("show_revoked", sgqlc.types.Arg(Boolean, graphql_name="showRevoked", default=False)),)), + ) + delivery_method = sgqlc.types.Field("SubscriptionDeliveryMethod", graphql_name="deliveryMethod") + delivery_price = sgqlc.types.Field(sgqlc.types.non_null("MoneyV2"), graphql_name="deliveryPrice") + discounts = sgqlc.types.Field( + sgqlc.types.non_null("SubscriptionManualDiscountConnection"), + graphql_name="discounts", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + line_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="lineCount") + lines = sgqlc.types.Field( + sgqlc.types.non_null("SubscriptionLineConnection"), + graphql_name="lines", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + note = sgqlc.types.Field(String, graphql_name="note") + orders = sgqlc.types.Field( + sgqlc.types.non_null("OrderConnection"), + graphql_name="orders", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") + + +class Catalog(sgqlc.types.Interface): + __schema__ = shopify_schema + __field_names__ = ("id", "operations", "price_list", "publication", "status", "title") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + operations = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourceOperation))), graphql_name="operations" + ) + price_list = sgqlc.types.Field("PriceList", graphql_name="priceList") + publication = sgqlc.types.Field("Publication", graphql_name="publication") + status = sgqlc.types.Field(sgqlc.types.non_null(CatalogStatus), graphql_name="status") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + +class AbandonmentEmailStateUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("abandonment", "user_errors") + abandonment = sgqlc.types.Field("Abandonment", graphql_name="abandonment") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AbandonmentEmailStateUpdateUserError"))), graphql_name="userErrors" + ) + + +class AbandonmentUpdateActivitiesDeliveryStatusesPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("abandonment", "user_errors") + abandonment = sgqlc.types.Field("Abandonment", graphql_name="abandonment") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AbandonmentUpdateActivitiesDeliveryStatusesUserError"))), + graphql_name="userErrors", + ) + + +class AccessScope(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("description", "handle") + description = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="description") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + + +class AllDiscountItems(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("all_items",) + all_items = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="allItems") + + +class ApiVersion(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("display_name", "handle", "supported") + display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + supported = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supported") + + +class AppConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("App"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class AppCreditConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppCreditEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppCredit"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class AppCreditEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("AppCredit"), graphql_name="node") + + +class AppDiscountType(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("app", "app_bridge", "app_key", "description", "discount_class", "function_id", "target_type", "title") + app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") + app_bridge = sgqlc.types.Field(sgqlc.types.non_null("FunctionsAppBridge"), graphql_name="appBridge") + app_key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="appKey") + description = sgqlc.types.Field(String, graphql_name="description") + discount_class = sgqlc.types.Field(sgqlc.types.non_null(DiscountClass), graphql_name="discountClass") + function_id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="functionId") + target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + +class AppEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="node") + + +class AppFeedback(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("app", "link", "messages") + app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") + link = sgqlc.types.Field("Link", graphql_name="link") + messages = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="messages") + + +class AppInstallationConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppInstallationEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppInstallation"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class AppInstallationEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") @@ -5950,16 +7943,6 @@ class AppPlanV2(sgqlc.types.Type): pricing_details = sgqlc.types.Field(sgqlc.types.non_null("AppPricingDetails"), graphql_name="pricingDetails") -class AppPurchase(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("created_at", "name", "price", "status", "test") - created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - price = sgqlc.types.Field(sgqlc.types.non_null("MoneyV2"), graphql_name="price") - status = sgqlc.types.Field(sgqlc.types.non_null(AppPurchaseStatus), graphql_name="status") - test = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="test") - - class AppPurchaseOneTimeConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -5997,12 +7980,10 @@ class AppRevenueAttributionRecordConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppRevenueAttributionRecordEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppRevenueAttributionRecordEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppRevenueAttributionRecord"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppRevenueAttributionRecord"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -6059,12 +8040,7 @@ class AppSubscriptionCreatePayload(sgqlc.types.Type): class AppSubscriptionDiscount(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "duration_limit_in_intervals", - "price_after_discount", - "remaining_duration_in_intervals", - "value", - ) + __field_names__ = ("duration_limit_in_intervals", "price_after_discount", "remaining_duration_in_intervals", "value") duration_limit_in_intervals = sgqlc.types.Field(Int, graphql_name="durationLimitInIntervals") price_after_discount = sgqlc.types.Field(sgqlc.types.non_null("MoneyV2"), graphql_name="priceAfterDiscount") remaining_duration_in_intervals = sgqlc.types.Field(Int, graphql_name="remainingDurationInIntervals") @@ -6124,8 +8100,7 @@ class AppSubscriptionTrialExtendPayload(sgqlc.types.Type): __field_names__ = ("app_subscription", "user_errors") app_subscription = sgqlc.types.Field("AppSubscription", graphql_name="appSubscription") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppSubscriptionTrialExtendUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppSubscriptionTrialExtendUserError"))), graphql_name="userErrors" ) @@ -6171,8 +8146,7 @@ class AvailableChannelDefinitionsByChannel(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("channel_definitions", "channel_name") channel_definitions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ChannelDefinition"))), - graphql_name="channelDefinitions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ChannelDefinition"))), graphql_name="channelDefinitions" ) channel_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="channelName") @@ -6189,8 +8163,7 @@ class BulkOperationRunMutationPayload(sgqlc.types.Type): __field_names__ = ("bulk_operation", "user_errors") bulk_operation = sgqlc.types.Field("BulkOperation", graphql_name="bulkOperation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BulkMutationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BulkMutationUserError"))), graphql_name="userErrors" ) @@ -6211,10 +8184,19 @@ class BulkProductResourceFeedbackCreatePayload(sgqlc.types.Type): ) +class BundlesFeature(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("eligible_for_bundles", "ineligibility_reason", "sells_bundles") + eligible_for_bundles = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="eligibleForBundles") + ineligibility_reason = sgqlc.types.Field(String, graphql_name="ineligibilityReason") + sells_bundles = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="sellsBundles") + + class BuyerExperienceConfiguration(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("checkout_to_draft", "pay_now_only", "payment_terms_template") + __field_names__ = ("checkout_to_draft", "editable_shipping_address", "pay_now_only", "payment_terms_template") checkout_to_draft = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="checkoutToDraft") + editable_shipping_address = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="editableShippingAddress") pay_now_only = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="payNowOnly") payment_terms_template = sgqlc.types.Field("PaymentTermsTemplate", graphql_name="paymentTermsTemplate") @@ -6223,39 +8205,17 @@ class CalculatedDiscountAllocation(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("allocated_amount_set", "discount_application") allocated_amount_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="allocatedAmountSet") - discount_application = sgqlc.types.Field(sgqlc.types.non_null("CalculatedDiscountApplication"), graphql_name="discountApplication") - - -class CalculatedDiscountApplication(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ( - "allocation_method", - "applied_to", - "description", - "id", - "target_selection", - "target_type", - "value", - ) - allocation_method = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationAllocationMethod), graphql_name="allocationMethod") - applied_to = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationLevel), graphql_name="appliedTo") - description = sgqlc.types.Field(String, graphql_name="description") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - target_selection = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetSelection), graphql_name="targetSelection") - target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") - value = sgqlc.types.Field(sgqlc.types.non_null("PricingValue"), graphql_name="value") + discount_application = sgqlc.types.Field(sgqlc.types.non_null(CalculatedDiscountApplication), graphql_name="discountApplication") class CalculatedDiscountApplicationConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CalculatedDiscountApplicationEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CalculatedDiscountApplicationEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CalculatedDiscountApplication))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CalculatedDiscountApplication))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -6297,8 +8257,7 @@ class CalculatedDraftOrder(sgqlc.types.Type): ) applied_discount = sgqlc.types.Field("DraftOrderAppliedDiscount", graphql_name="appliedDiscount") available_shipping_rates = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShippingRate"))), - graphql_name="availableShippingRates", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShippingRate"))), graphql_name="availableShippingRates" ) billing_address_matches_shipping_address = sgqlc.types.Field( sgqlc.types.non_null(Boolean), graphql_name="billingAddressMatchesShippingAddress" @@ -6306,8 +8265,7 @@ class CalculatedDraftOrder(sgqlc.types.Type): currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") customer = sgqlc.types.Field("Customer", graphql_name="customer") line_items = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CalculatedDraftOrderLineItem"))), - graphql_name="lineItems", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CalculatedDraftOrderLineItem"))), graphql_name="lineItems" ) line_items_subtotal_price = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="lineItemsSubtotalPrice") market_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="marketName") @@ -6367,8 +8325,7 @@ class CalculatedDraftOrderLineItem(sgqlc.types.Type): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" ) custom_attributes_v2 = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TypedAttribute"))), - graphql_name="customAttributesV2", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TypedAttribute"))), graphql_name="customAttributesV2" ) discounted_total = sgqlc.types.Field(sgqlc.types.non_null("MoneyV2"), graphql_name="discountedTotal") discounted_total_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="discountedTotalSet") @@ -6439,8 +8396,7 @@ class CalculatedLineItem(sgqlc.types.Type): restocking = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="restocking") sku = sgqlc.types.Field(String, graphql_name="sku") staged_changes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderStagedChange"))), - graphql_name="stagedChanges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderStagedChange"))), graphql_name="stagedChanges" ) title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") uneditable_subtotal_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="uneditableSubtotalSet") @@ -6465,6 +8421,115 @@ class CalculatedLineItemEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null(CalculatedLineItem), graphql_name="node") +class CardPaymentDetails(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ( + "avs_result_code", + "bin", + "company", + "cvv_result_code", + "expiration_month", + "expiration_year", + "name", + "number", + "wallet", + ) + avs_result_code = sgqlc.types.Field(String, graphql_name="avsResultCode") + bin = sgqlc.types.Field(String, graphql_name="bin") + company = sgqlc.types.Field(String, graphql_name="company") + cvv_result_code = sgqlc.types.Field(String, graphql_name="cvvResultCode") + expiration_month = sgqlc.types.Field(Int, graphql_name="expirationMonth") + expiration_year = sgqlc.types.Field(Int, graphql_name="expirationYear") + name = sgqlc.types.Field(String, graphql_name="name") + number = sgqlc.types.Field(String, graphql_name="number") + wallet = sgqlc.types.Field(DigitalWallet, graphql_name="wallet") + + +class CartTransformConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CartTransformEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CartTransform"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class CartTransformCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cart_transform", "user_errors") + cart_transform = sgqlc.types.Field("CartTransform", graphql_name="cartTransform") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CartTransformCreateUserError"))), graphql_name="userErrors" + ) + + +class CartTransformDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CartTransformDeleteUserError"))), graphql_name="userErrors" + ) + + +class CartTransformEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("CartTransform"), graphql_name="node") + + +class CatalogConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info", "total_count") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CatalogEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Catalog))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + total_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="totalCount") + + +class CatalogContextUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("catalog", "user_errors") + catalog = sgqlc.types.Field(Catalog, graphql_name="catalog") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CatalogUserError"))), graphql_name="userErrors" + ) + + +class CatalogCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("catalog", "user_errors") + catalog = sgqlc.types.Field(Catalog, graphql_name="catalog") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CatalogUserError"))), graphql_name="userErrors" + ) + + +class CatalogDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CatalogUserError"))), graphql_name="userErrors" + ) + + +class CatalogEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(Catalog), graphql_name="node") + + +class CatalogUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("catalog", "user_errors") + catalog = sgqlc.types.Field(Catalog, graphql_name="catalog") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CatalogUserError"))), graphql_name="userErrors" + ) + + class ChannelConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -6507,8 +8572,7 @@ class CollectionAddProductsV2Payload(sgqlc.types.Type): __field_names__ = ("job", "user_errors") job = sgqlc.types.Field("Job", graphql_name="job") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CollectionAddProductsV2UserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CollectionAddProductsV2UserError"))), graphql_name="userErrors" ) @@ -6555,8 +8619,7 @@ class CollectionPublicationConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CollectionPublicationEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CollectionPublicationEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionPublication))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -6605,15 +8668,21 @@ class CollectionRule(sgqlc.types.Type): class CollectionRuleConditions(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("allowed_relations", "default_relation", "rule_type") + __field_names__ = ("allowed_relations", "default_relation", "rule_object", "rule_type") allowed_relations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionRuleRelation))), - graphql_name="allowedRelations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionRuleRelation))), graphql_name="allowedRelations" ) default_relation = sgqlc.types.Field(sgqlc.types.non_null(CollectionRuleRelation), graphql_name="defaultRelation") + rule_object = sgqlc.types.Field("CollectionRuleConditionsRuleObject", graphql_name="ruleObject") rule_type = sgqlc.types.Field(sgqlc.types.non_null(CollectionRuleColumn), graphql_name="ruleType") +class CollectionRuleMetafieldCondition(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("metafield_definition",) + metafield_definition = sgqlc.types.Field(sgqlc.types.non_null("MetafieldDefinition"), graphql_name="metafieldDefinition") + + class CollectionRuleProductCategoryCondition(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("value",) @@ -6660,20 +8729,12 @@ class CommentEventAttachment(sgqlc.types.Type): url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") -class CommentEventSubject(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("has_timeline_comment", "id") - has_timeline_comment = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="hasTimelineComment") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - - class CompaniesDeletePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("deleted_company_ids", "user_errors") deleted_company_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedCompanyIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6682,8 +8743,7 @@ class CompanyAddressDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_address_id", "user_errors") deleted_address_id = sgqlc.types.Field(ID, graphql_name="deletedAddressId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6692,8 +8752,7 @@ class CompanyAssignCustomerAsContactPayload(sgqlc.types.Type): __field_names__ = ("company_contact", "user_errors") company_contact = sgqlc.types.Field("CompanyContact", graphql_name="companyContact") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6702,8 +8761,7 @@ class CompanyAssignMainContactPayload(sgqlc.types.Type): __field_names__ = ("company", "user_errors") company = sgqlc.types.Field("Company", graphql_name="company") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6720,8 +8778,7 @@ class CompanyContactAssignRolePayload(sgqlc.types.Type): __field_names__ = ("company_contact_role_assignment", "user_errors") company_contact_role_assignment = sgqlc.types.Field("CompanyContactRoleAssignment", graphql_name="companyContactRoleAssignment") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6732,8 +8789,7 @@ class CompanyContactAssignRolesPayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignment")), graphql_name="roleAssignments" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6750,8 +8806,7 @@ class CompanyContactCreatePayload(sgqlc.types.Type): __field_names__ = ("company_contact", "user_errors") company_contact = sgqlc.types.Field("CompanyContact", graphql_name="companyContact") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6760,8 +8815,7 @@ class CompanyContactDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_company_contact_id", "user_errors") deleted_company_contact_id = sgqlc.types.Field(ID, graphql_name="deletedCompanyContactId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6772,13 +8826,21 @@ class CompanyContactEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("CompanyContact"), graphql_name="node") +class CompanyContactRemoveFromCompanyPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("removed_company_contact_id", "user_errors") + removed_company_contact_id = sgqlc.types.Field(ID, graphql_name="removedCompanyContactId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" + ) + + class CompanyContactRevokeRolePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("revoked_company_contact_role_assignment_id", "user_errors") revoked_company_contact_role_assignment_id = sgqlc.types.Field(ID, graphql_name="revokedCompanyContactRoleAssignmentId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6787,8 +8849,7 @@ class CompanyContactRevokeRolesPayload(sgqlc.types.Type): __field_names__ = ("revoked_role_assignment_ids", "user_errors") revoked_role_assignment_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="revokedRoleAssignmentIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6796,12 +8857,10 @@ class CompanyContactRoleAssignmentConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignmentEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignmentEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignment"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignment"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -6830,13 +8889,21 @@ class CompanyContactRoleEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("CompanyContactRole"), graphql_name="node") +class CompanyContactSendWelcomeEmailPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("company_contact", "user_errors") + company_contact = sgqlc.types.Field("CompanyContact", graphql_name="companyContact") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" + ) + + class CompanyContactUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("company_contact", "user_errors") company_contact = sgqlc.types.Field("CompanyContact", graphql_name="companyContact") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6845,8 +8912,7 @@ class CompanyContactsDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_company_contact_ids", "user_errors") deleted_company_contact_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedCompanyContactIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6855,8 +8921,7 @@ class CompanyCreatePayload(sgqlc.types.Type): __field_names__ = ("company", "user_errors") company = sgqlc.types.Field("Company", graphql_name="company") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6865,8 +8930,7 @@ class CompanyDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_company_id", "user_errors") deleted_company_id = sgqlc.types.Field(ID, graphql_name="deletedCompanyId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6882,8 +8946,7 @@ class CompanyLocationAssignAddressPayload(sgqlc.types.Type): __field_names__ = ("addresses", "user_errors") addresses = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("CompanyAddress")), graphql_name="addresses") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6894,8 +8957,7 @@ class CompanyLocationAssignRolesPayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null("CompanyContactRoleAssignment")), graphql_name="roleAssignments" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6904,8 +8966,7 @@ class CompanyLocationAssignTaxExemptionsPayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6922,8 +8983,7 @@ class CompanyLocationCreatePayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6932,8 +8992,7 @@ class CompanyLocationCreateTaxRegistrationPayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6942,8 +9001,7 @@ class CompanyLocationDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_company_location_id", "user_errors") deleted_company_location_id = sgqlc.types.Field(ID, graphql_name="deletedCompanyLocationId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6959,8 +9017,7 @@ class CompanyLocationRevokeRolesPayload(sgqlc.types.Type): __field_names__ = ("revoked_role_assignment_ids", "user_errors") revoked_role_assignment_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="revokedRoleAssignmentIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6969,8 +9026,7 @@ class CompanyLocationRevokeTaxExemptionsPayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6979,8 +9035,7 @@ class CompanyLocationRevokeTaxRegistrationPayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -6989,8 +9044,7 @@ class CompanyLocationUpdatePayload(sgqlc.types.Type): __field_names__ = ("company_location", "user_errors") company_location = sgqlc.types.Field("CompanyLocation", graphql_name="companyLocation") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -7001,8 +9055,7 @@ class CompanyLocationsDeletePayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedCompanyLocationIds" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -7011,8 +9064,7 @@ class CompanyRevokeMainContactPayload(sgqlc.types.Type): __field_names__ = ("company", "user_errors") company = sgqlc.types.Field("Company", graphql_name="company") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -7021,8 +9073,7 @@ class CompanyUpdatePayload(sgqlc.types.Type): __field_names__ = ("company", "user_errors") company = sgqlc.types.Field("Company", graphql_name="company") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BusinessCustomerUserError"))), graphql_name="userErrors" ) @@ -7046,12 +9097,10 @@ class CountryHarmonizedSystemCodeConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CountryHarmonizedSystemCodeEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CountryHarmonizedSystemCodeEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CountryHarmonizedSystemCode))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CountryHarmonizedSystemCode))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -7065,12 +9114,7 @@ class CountryHarmonizedSystemCodeEdge(sgqlc.types.Type): class CurrencyFormats(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "money_format", - "money_in_emails_format", - "money_with_currency_format", - "money_with_currency_in_emails_format", - ) + __field_names__ = ("money_format", "money_in_emails_format", "money_with_currency_format", "money_with_currency_in_emails_format") money_format = sgqlc.types.Field(sgqlc.types.non_null(FormattedString), graphql_name="moneyFormat") money_in_emails_format = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="moneyInEmailsFormat") money_with_currency_format = sgqlc.types.Field(sgqlc.types.non_null(FormattedString), graphql_name="moneyWithCurrencyFormat") @@ -7155,11 +9199,13 @@ class CustomerCreditCard(sgqlc.types.Type): class CustomerCreditCardBillingAddress(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("address1", "city", "country", "country_code", "province", "province_code", "zip") + __field_names__ = ("address1", "city", "country", "country_code", "first_name", "last_name", "province", "province_code", "zip") address1 = sgqlc.types.Field(String, graphql_name="address1") city = sgqlc.types.Field(String, graphql_name="city") country = sgqlc.types.Field(String, graphql_name="country") country_code = sgqlc.types.Field(CountryCode, graphql_name="countryCode") + first_name = sgqlc.types.Field(String, graphql_name="firstName") + last_name = sgqlc.types.Field(String, graphql_name="lastName") province = sgqlc.types.Field(String, graphql_name="province") province_code = sgqlc.types.Field(String, graphql_name="provinceCode") zip = sgqlc.types.Field(String, graphql_name="zip") @@ -7182,13 +9228,7 @@ class CustomerEdge(sgqlc.types.Type): class CustomerEmailAddress(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "email_address", - "marketing_state", - "marketing_unsubscribe_url", - "open_tracking_level", - "open_tracking_url", - ) + __field_names__ = ("email_address", "marketing_state", "marketing_unsubscribe_url", "open_tracking_level", "open_tracking_url") email_address = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="emailAddress") marketing_state = sgqlc.types.Field(sgqlc.types.non_null(CustomerEmailAddressMarketingState), graphql_name="marketingState") marketing_unsubscribe_url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="marketingUnsubscribeUrl") @@ -7228,27 +9268,172 @@ class CustomerJourney(sgqlc.types.Type): days_to_conversion = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="daysToConversion") first_visit = sgqlc.types.Field(sgqlc.types.non_null("CustomerVisit"), graphql_name="firstVisit") last_visit = sgqlc.types.Field("CustomerVisit", graphql_name="lastVisit") - moments = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerMoment"))), graphql_name="moments") + moments = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CustomerMoment))), graphql_name="moments") class CustomerJourneySummary(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("customer_order_index", "days_to_conversion", "first_visit", "last_visit", "moments", "moments_count", "ready") + customer_order_index = sgqlc.types.Field(Int, graphql_name="customerOrderIndex") + days_to_conversion = sgqlc.types.Field(Int, graphql_name="daysToConversion") + first_visit = sgqlc.types.Field("CustomerVisit", graphql_name="firstVisit") + last_visit = sgqlc.types.Field("CustomerVisit", graphql_name="lastVisit") + moments = sgqlc.types.Field( + "CustomerMomentConnection", + graphql_name="moments", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + moments_count = sgqlc.types.Field(Int, graphql_name="momentsCount") + ready = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="ready") + + +class CustomerMergeError(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("error_fields", "message") + error_fields = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CustomerMergeErrorFieldType))), graphql_name="errorFields" + ) + message = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="message") + + +class CustomerMergePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("job", "resulting_customer_id", "user_errors") + job = sgqlc.types.Field("Job", graphql_name="job") + resulting_customer_id = sgqlc.types.Field(ID, graphql_name="resultingCustomerId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerMergeUserError"))), graphql_name="userErrors" + ) + + +class CustomerMergePreview(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("alternate_fields", "blocking_fields", "customer_merge_errors", "default_fields", "resulting_customer_id") + alternate_fields = sgqlc.types.Field("CustomerMergePreviewAlternateFields", graphql_name="alternateFields") + blocking_fields = sgqlc.types.Field("CustomerMergePreviewBlockingFields", graphql_name="blockingFields") + customer_merge_errors = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(CustomerMergeError)), graphql_name="customerMergeErrors" + ) + default_fields = sgqlc.types.Field("CustomerMergePreviewDefaultFields", graphql_name="defaultFields") + resulting_customer_id = sgqlc.types.Field(ID, graphql_name="resultingCustomerId") + + +class CustomerMergePreviewAlternateFields(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("default_address", "email", "first_name", "last_name", "phone_number") + default_address = sgqlc.types.Field("MailingAddress", graphql_name="defaultAddress") + email = sgqlc.types.Field(CustomerEmailAddress, graphql_name="email") + first_name = sgqlc.types.Field(String, graphql_name="firstName") + last_name = sgqlc.types.Field(String, graphql_name="lastName") + phone_number = sgqlc.types.Field("CustomerPhoneNumber", graphql_name="phoneNumber") + + +class CustomerMergePreviewBlockingFields(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("note", "tags") + note = sgqlc.types.Field(String, graphql_name="note") + tags = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags") + + +class CustomerMergePreviewDefaultFields(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( - "customer_order_index", - "days_to_conversion", - "first_visit", - "last_visit", - "moments", - "moments_count", - "ready", + "addresses", + "default_address", + "discount_node_count", + "discount_nodes", + "display_name", + "draft_order_count", + "draft_orders", + "email", + "first_name", + "gift_card_count", + "gift_cards", + "last_name", + "metafield_count", + "note", + "order_count", + "orders", + "phone_number", + "tags", + ) + addresses = sgqlc.types.Field( + sgqlc.types.non_null("MailingAddressConnection"), + graphql_name="addresses", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + default_address = sgqlc.types.Field("MailingAddress", graphql_name="defaultAddress") + discount_node_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="discountNodeCount") + discount_nodes = sgqlc.types.Field( + sgqlc.types.non_null("DiscountNodeConnection"), + graphql_name="discountNodes", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(DiscountSortKeys, graphql_name="sortKey", default="CREATED_AT")), + ) + ), + ) + display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") + draft_order_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="draftOrderCount") + draft_orders = sgqlc.types.Field( + sgqlc.types.non_null("DraftOrderConnection"), + graphql_name="draftOrders", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(DraftOrderSortKeys, graphql_name="sortKey", default="UPDATED_AT")), + ) + ), + ) + email = sgqlc.types.Field(CustomerEmailAddress, graphql_name="email") + first_name = sgqlc.types.Field(String, graphql_name="firstName") + gift_card_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="giftCardCount") + gift_cards = sgqlc.types.Field( + sgqlc.types.non_null("GiftCardConnection"), + graphql_name="giftCards", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(GiftCardSortKeys, graphql_name="sortKey", default="CREATED_AT")), + ) + ), ) - customer_order_index = sgqlc.types.Field(Int, graphql_name="customerOrderIndex") - days_to_conversion = sgqlc.types.Field(Int, graphql_name="daysToConversion") - first_visit = sgqlc.types.Field("CustomerVisit", graphql_name="firstVisit") - last_visit = sgqlc.types.Field("CustomerVisit", graphql_name="lastVisit") - moments = sgqlc.types.Field( - "CustomerMomentConnection", - graphql_name="moments", + last_name = sgqlc.types.Field(String, graphql_name="lastName") + metafield_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="metafieldCount") + note = sgqlc.types.Field(String, graphql_name="note") + order_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="orderCount") + orders = sgqlc.types.Field( + sgqlc.types.non_null("OrderConnection"), + graphql_name="orders", args=sgqlc.types.ArgDict( ( ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -7256,17 +9441,34 @@ class CustomerJourneySummary(sgqlc.types.Type): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(OrderSortKeys, graphql_name="sortKey", default="PROCESSED_AT")), ) ), ) - moments_count = sgqlc.types.Field(Int, graphql_name="momentsCount") - ready = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="ready") + phone_number = sgqlc.types.Field("CustomerPhoneNumber", graphql_name="phoneNumber") + tags = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags") -class CustomerMoment(sgqlc.types.Interface): +class CustomerMergeRequest(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("occurred_at",) - occurred_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="occurredAt") + __field_names__ = ("customer_merge_errors", "job_id", "resulting_customer_id", "status") + customer_merge_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CustomerMergeError))), graphql_name="customerMergeErrors" + ) + job_id = sgqlc.types.Field(ID, graphql_name="jobId") + resulting_customer_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="resultingCustomerId") + status = sgqlc.types.Field(sgqlc.types.non_null(CustomerMergeRequestStatus), graphql_name="status") + + +class CustomerMergeable(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("error_fields", "is_mergeable", "merge_in_progress", "reason") + error_fields = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CustomerMergeErrorFieldType))), graphql_name="errorFields" + ) + is_mergeable = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isMergeable") + merge_in_progress = sgqlc.types.Field(CustomerMergeRequest, graphql_name="mergeInProgress") + reason = sgqlc.types.Field(String, graphql_name="reason") class CustomerMomentConnection(sgqlc.types.relay.Connection): @@ -7301,8 +9503,7 @@ class CustomerPaymentMethodConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethod"))), graphql_name="nodes" @@ -7310,6 +9511,16 @@ class CustomerPaymentMethodConnection(sgqlc.types.relay.Connection): page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") +class CustomerPaymentMethodCreateFromDuplicationDataPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("customer_payment_method", "user_errors") + customer_payment_method = sgqlc.types.Field("CustomerPaymentMethod", graphql_name="customerPaymentMethod") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodCreateFromDuplicationDataUserError"))), + graphql_name="userErrors", + ) + + class CustomerPaymentMethodCreditCardCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("customer_payment_method", "user_errors") @@ -7331,6 +9542,16 @@ class CustomerPaymentMethodEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("CustomerPaymentMethod"), graphql_name="node") +class CustomerPaymentMethodGetDuplicationDataPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("encrypted_duplication_data", "user_errors") + encrypted_duplication_data = sgqlc.types.Field(String, graphql_name="encryptedDuplicationData") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodGetDuplicationDataUserError"))), + graphql_name="userErrors", + ) + + class CustomerPaymentMethodGetUpdateUrlPayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("update_payment_method_url", "user_errors") @@ -7346,8 +9567,7 @@ class CustomerPaymentMethodPaypalBillingAgreementCreatePayload(sgqlc.types.Type) __field_names__ = ("customer_payment_method", "user_errors") customer_payment_method = sgqlc.types.Field("CustomerPaymentMethod", graphql_name="customerPaymentMethod") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), graphql_name="userErrors" ) @@ -7356,8 +9576,7 @@ class CustomerPaymentMethodPaypalBillingAgreementUpdatePayload(sgqlc.types.Type) __field_names__ = ("customer_payment_method", "user_errors") customer_payment_method = sgqlc.types.Field("CustomerPaymentMethod", graphql_name="customerPaymentMethod") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), graphql_name="userErrors" ) @@ -7366,8 +9585,7 @@ class CustomerPaymentMethodRemoteCreatePayload(sgqlc.types.Type): __field_names__ = ("customer_payment_method", "user_errors") customer_payment_method = sgqlc.types.Field("CustomerPaymentMethod", graphql_name="customerPaymentMethod") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodRemoteUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodRemoteUserError"))), graphql_name="userErrors" ) @@ -7376,8 +9594,7 @@ class CustomerPaymentMethodRemoteCreditCardCreatePayload(sgqlc.types.Type): __field_names__ = ("customer_payment_method", "user_errors") customer_payment_method = sgqlc.types.Field("CustomerPaymentMethod", graphql_name="customerPaymentMethod") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerPaymentMethodUserError"))), graphql_name="userErrors" ) @@ -7425,55 +9642,37 @@ class CustomerReplaceTaxExemptionsPayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") -class CustomerSegmentMember(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ( - "amount_spent", - "default_address", - "default_email_address", - "default_phone_number", - "display_name", - "first_name", - "id", - "last_name", - "last_order_id", - "note", - "number_of_orders", - ) - amount_spent = sgqlc.types.Field("MoneyV2", graphql_name="amountSpent") - default_address = sgqlc.types.Field("MailingAddress", graphql_name="defaultAddress") - default_email_address = sgqlc.types.Field(CustomerEmailAddress, graphql_name="defaultEmailAddress") - default_phone_number = sgqlc.types.Field(CustomerPhoneNumber, graphql_name="defaultPhoneNumber") - display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") - first_name = sgqlc.types.Field(String, graphql_name="firstName") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - last_name = sgqlc.types.Field(String, graphql_name="lastName") - last_order_id = sgqlc.types.Field(ID, graphql_name="lastOrderId") - note = sgqlc.types.Field(String, graphql_name="note") - number_of_orders = sgqlc.types.Field(UnsignedInt64, graphql_name="numberOfOrders") - - class CustomerSegmentMemberConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema - __field_names__ = ("edges", "page_info", "statistics") + __field_names__ = ("edges", "page_info", "statistics", "total_count") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerSegmentMemberEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerSegmentMemberEdge"))), graphql_name="edges" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") statistics = sgqlc.types.Field(sgqlc.types.non_null("SegmentStatistics"), graphql_name="statistics") + total_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="totalCount") class CustomerSegmentMemberEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(CustomerSegmentMember), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null("CustomerSegmentMember"), graphql_name="node") + + +class CustomerSegmentMembersQueryCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("customer_segment_members_query", "user_errors") + customer_segment_members_query = sgqlc.types.Field("CustomerSegmentMembersQuery", graphql_name="customerSegmentMembersQuery") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerSegmentMembersQueryUserError"))), graphql_name="userErrors" + ) class CustomerShopPayAgreement(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( + "billing_address", "expires_soon", "expiry_month", "expiry_year", @@ -7483,6 +9682,7 @@ class CustomerShopPayAgreement(sgqlc.types.Type): "masked_number", "name", ) + billing_address = sgqlc.types.Field(CustomerCreditCardBillingAddress, graphql_name="billingAddress") expires_soon = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="expiresSoon") expiry_month = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="expiryMonth") expiry_year = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="expiryYear") @@ -7507,8 +9707,7 @@ class CustomerSmsMarketingConsentUpdatePayload(sgqlc.types.Type): __field_names__ = ("customer", "user_errors") customer = sgqlc.types.Field("Customer", graphql_name="customer") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerSmsMarketingConsentError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerSmsMarketingConsentError"))), graphql_name="userErrors" ) @@ -7532,6 +9731,33 @@ class CustomerUpdatePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class CustomerVisitProductInfo(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("product", "quantity", "variant") + product = sgqlc.types.Field("Product", graphql_name="product") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + variant = sgqlc.types.Field("ProductVariant", graphql_name="variant") + + +class CustomerVisitProductInfoConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("CustomerVisitProductInfoEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CustomerVisitProductInfo))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class CustomerVisitProductInfoEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(CustomerVisitProductInfo), graphql_name="node") + + class DelegateAccessToken(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("access_scopes", "access_token", "created_at") @@ -7546,8 +9772,17 @@ class DelegateAccessTokenCreatePayload(sgqlc.types.Type): delegate_access_token = sgqlc.types.Field(DelegateAccessToken, graphql_name="delegateAccessToken") shop = sgqlc.types.Field(sgqlc.types.non_null("Shop"), graphql_name="shop") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DelegateAccessTokenCreateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DelegateAccessTokenCreateUserError"))), graphql_name="userErrors" + ) + + +class DelegateAccessTokenDestroyPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("shop", "status", "user_errors") + shop = sgqlc.types.Field(sgqlc.types.non_null("Shop"), graphql_name="shop") + status = sgqlc.types.Field(Boolean, graphql_name="status") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DelegateAccessTokenDestroyUserError"))), graphql_name="userErrors" ) @@ -7581,6 +9816,13 @@ class DeliveryAvailableService(sgqlc.types.Type): name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") +class DeliveryBrandedPromise(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("handle", "name") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + + class DeliveryCarrierServiceAndLocations(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("carrier_service", "locations") @@ -7611,6 +9853,61 @@ class DeliveryCountryCodesOrRestOfWorld(sgqlc.types.Type): rest_of_world = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="restOfWorld") +class DeliveryCustomizationActivationPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("ids", "user_errors") + ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="ids") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomizationError"))), graphql_name="userErrors" + ) + + +class DeliveryCustomizationConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomizationEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomization"))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class DeliveryCustomizationCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("delivery_customization", "user_errors") + delivery_customization = sgqlc.types.Field("DeliveryCustomization", graphql_name="deliveryCustomization") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomizationError"))), graphql_name="userErrors" + ) + + +class DeliveryCustomizationDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomizationError"))), graphql_name="userErrors" + ) + + +class DeliveryCustomizationEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("DeliveryCustomization"), graphql_name="node") + + +class DeliveryCustomizationUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("delivery_customization", "user_errors") + delivery_customization = sgqlc.types.Field("DeliveryCustomization", graphql_name="deliveryCustomization") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryCustomizationError"))), graphql_name="userErrors" + ) + + class DeliveryLegacyModeBlocked(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("blocked", "reasons") @@ -7618,6 +9915,13 @@ class DeliveryLegacyModeBlocked(sgqlc.types.Type): reasons = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryLegacyModeBlockedReason)), graphql_name="reasons") +class DeliveryLocalPickupSettings(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("instructions", "pickup_time") + instructions = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="instructions") + pickup_time = sgqlc.types.Field(sgqlc.types.non_null(DeliveryLocalPickupTime), graphql_name="pickupTime") + + class DeliveryLocationGroupZone(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("method_definition_counts", "method_definitions", "zone") @@ -7647,8 +9951,7 @@ class DeliveryLocationGroupZoneConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryLocationGroupZoneEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryLocationGroupZoneEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryLocationGroupZone))), graphql_name="nodes" @@ -7667,12 +9970,10 @@ class DeliveryMethodDefinitionConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinitionEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinition"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryMethodDefinition"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -7741,8 +10042,7 @@ class DeliveryProfileLocationGroup(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("countries_in_any_zone", "location_group", "location_group_zones") countries_in_any_zone = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryCountryAndZone))), - graphql_name="countriesInAnyZone", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryCountryAndZone))), graphql_name="countriesInAnyZone" ) location_group = sgqlc.types.Field(sgqlc.types.non_null("DeliveryLocationGroup"), graphql_name="locationGroup") location_group_zones = sgqlc.types.Field( @@ -7784,7 +10084,7 @@ class DiscountAllocation(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("allocated_amount_set", "discount_application") allocated_amount_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="allocatedAmountSet") - discount_application = sgqlc.types.Field(sgqlc.types.non_null("DiscountApplication"), graphql_name="discountApplication") + discount_application = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplication), graphql_name="discountApplication") class DiscountAmount(sgqlc.types.Type): @@ -7794,16 +10094,6 @@ class DiscountAmount(sgqlc.types.Type): applies_on_each_item = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="appliesOnEachItem") -class DiscountApplication(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("allocation_method", "index", "target_selection", "target_type", "value") - allocation_method = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationAllocationMethod), graphql_name="allocationMethod") - index = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="index") - target_selection = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetSelection), graphql_name="targetSelection") - target_type = sgqlc.types.Field(sgqlc.types.non_null(DiscountApplicationTargetType), graphql_name="targetType") - value = sgqlc.types.Field(sgqlc.types.non_null("PricingValue"), graphql_name="value") - - class DiscountApplicationConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -7834,7 +10124,9 @@ class DiscountAutomaticApp(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( "app_discount_type", + "async_usage_count", "combines_with", + "created_at", "discount_class", "discount_id", "ends_at", @@ -7842,9 +10134,12 @@ class DiscountAutomaticApp(sgqlc.types.Type): "starts_at", "status", "title", + "updated_at", ) app_discount_type = sgqlc.types.Field(sgqlc.types.non_null(AppDiscountType), graphql_name="appDiscountType") + async_usage_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="asyncUsageCount") combines_with = sgqlc.types.Field(sgqlc.types.non_null("DiscountCombinesWith"), graphql_name="combinesWith") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") discount_class = sgqlc.types.Field(sgqlc.types.non_null(DiscountClass), graphql_name="discountClass") discount_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="discountId") ends_at = sgqlc.types.Field(DateTime, graphql_name="endsAt") @@ -7852,6 +10147,7 @@ class DiscountAutomaticApp(sgqlc.types.Type): starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") status = sgqlc.types.Field(sgqlc.types.non_null(DiscountStatus), graphql_name="status") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") class DiscountAutomaticAppCreatePayload(sgqlc.types.Type): @@ -7887,6 +10183,7 @@ class DiscountAutomaticBasic(sgqlc.types.Type): "status", "summary", "title", + "updated_at", ) async_usage_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="asyncUsageCount") combines_with = sgqlc.types.Field(sgqlc.types.non_null("DiscountCombinesWith"), graphql_name="combinesWith") @@ -7900,6 +10197,7 @@ class DiscountAutomaticBasic(sgqlc.types.Type): status = sgqlc.types.Field(sgqlc.types.non_null(DiscountStatus), graphql_name="status") summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") class DiscountAutomaticBasicCreatePayload(sgqlc.types.Type): @@ -7986,8 +10284,7 @@ class DiscountAutomaticNodeConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountAutomaticNodeEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountAutomaticNodeEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountAutomaticNode"))), graphql_name="nodes" @@ -8033,6 +10330,7 @@ class DiscountCodeApp(sgqlc.types.Type): "status", "title", "total_sales", + "updated_at", "usage_limit", ) app_discount_type = sgqlc.types.Field(sgqlc.types.non_null(AppDiscountType), graphql_name="appDiscountType") @@ -8065,13 +10363,13 @@ class DiscountCodeApp(sgqlc.types.Type): has_timeline_comment = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="hasTimelineComment") recurring_cycle_limit = sgqlc.types.Field(Int, graphql_name="recurringCycleLimit") shareable_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), - graphql_name="shareableUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), graphql_name="shareableUrls" ) starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") status = sgqlc.types.Field(sgqlc.types.non_null(DiscountStatus), graphql_name="status") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") total_sales = sgqlc.types.Field("MoneyV2", graphql_name="totalSales") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") usage_limit = sgqlc.types.Field(Int, graphql_name="usageLimit") @@ -8116,6 +10414,7 @@ class DiscountCodeBasic(sgqlc.types.Type): "summary", "title", "total_sales", + "updated_at", "usage_limit", ) applies_once_per_customer = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="appliesOncePerCustomer") @@ -8147,8 +10446,7 @@ class DiscountCodeBasic(sgqlc.types.Type): minimum_requirement = sgqlc.types.Field("DiscountMinimumRequirement", graphql_name="minimumRequirement") recurring_cycle_limit = sgqlc.types.Field(Int, graphql_name="recurringCycleLimit") shareable_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), - graphql_name="shareableUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), graphql_name="shareableUrls" ) short_summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="shortSummary") starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") @@ -8156,6 +10454,7 @@ class DiscountCodeBasic(sgqlc.types.Type): summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") total_sales = sgqlc.types.Field("MoneyV2", graphql_name="totalSales") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") usage_limit = sgqlc.types.Field(Int, graphql_name="usageLimit") @@ -8225,6 +10524,7 @@ class DiscountCodeBxgy(sgqlc.types.Type): "summary", "title", "total_sales", + "updated_at", "usage_limit", "uses_per_order_limit", ) @@ -8256,14 +10556,14 @@ class DiscountCodeBxgy(sgqlc.types.Type): ends_at = sgqlc.types.Field(DateTime, graphql_name="endsAt") has_timeline_comment = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="hasTimelineComment") shareable_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), - graphql_name="shareableUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), graphql_name="shareableUrls" ) starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") status = sgqlc.types.Field(sgqlc.types.non_null(DiscountStatus), graphql_name="status") summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") total_sales = sgqlc.types.Field("MoneyV2", graphql_name="totalSales") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") usage_limit = sgqlc.types.Field(Int, graphql_name="usageLimit") uses_per_order_limit = sgqlc.types.Field(Int, graphql_name="usesPerOrderLimit") @@ -8330,6 +10630,7 @@ class DiscountCodeFreeShipping(sgqlc.types.Type): "summary", "title", "total_sales", + "updated_at", "usage_limit", ) applies_on_one_time_purchase = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="appliesOnOneTimePurchase") @@ -8366,8 +10667,7 @@ class DiscountCodeFreeShipping(sgqlc.types.Type): minimum_requirement = sgqlc.types.Field("DiscountMinimumRequirement", graphql_name="minimumRequirement") recurring_cycle_limit = sgqlc.types.Field(Int, graphql_name="recurringCycleLimit") shareable_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), - graphql_name="shareableUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountShareableUrl"))), graphql_name="shareableUrls" ) short_summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="shortSummary") starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") @@ -8375,6 +10675,7 @@ class DiscountCodeFreeShipping(sgqlc.types.Type): summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") total_sales = sgqlc.types.Field("MoneyV2", graphql_name="totalSales") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") usage_limit = sgqlc.types.Field(Int, graphql_name="usageLimit") @@ -8606,12 +10907,10 @@ class DiscountRedeemCodeBulkCreationCodeConnection(sgqlc.types.relay.Connection) __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountRedeemCodeBulkCreationCodeEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DiscountRedeemCodeBulkCreationCodeEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountRedeemCodeBulkCreationCode))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountRedeemCodeBulkCreationCode))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -8649,20 +10948,12 @@ class DiscountShareableUrl(sgqlc.types.Type): url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") -class DisplayableError(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("field", "message") - field = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="field") - message = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="message") - - class DisputeEvidenceUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("dispute_evidence", "user_errors") dispute_evidence = sgqlc.types.Field("ShopifyPaymentsDisputeEvidence", graphql_name="disputeEvidence") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DisputeEvidenceUpdateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DisputeEvidenceUpdateUserError"))), graphql_name="userErrors" ) @@ -8817,24 +11108,20 @@ class EditableProperty(sgqlc.types.Type): reason = sgqlc.types.Field(FormattedString, graphql_name="reason") -class Event(sgqlc.types.Interface): +class ErrorPosition(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "app_title", - "attribute_to_app", - "attribute_to_user", - "created_at", - "critical_alert", - "id", - "message", + __field_names__ = ("character", "line") + character = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="character") + line = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="line") + + +class EventBridgeServerPixelUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("server_pixel", "user_errors") + server_pixel = sgqlc.types.Field("ServerPixel", graphql_name="serverPixel") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsServerPixelUserError"))), graphql_name="userErrors" ) - app_title = sgqlc.types.Field(String, graphql_name="appTitle") - attribute_to_app = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="attributeToApp") - attribute_to_user = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="attributeToUser") - created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") - critical_alert = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="criticalAlert") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - message = sgqlc.types.Field(sgqlc.types.non_null(FormattedString), graphql_name="message") class EventBridgeWebhookSubscriptionCreatePayload(sgqlc.types.Type): @@ -8859,11 +11146,105 @@ class EventConnection(sgqlc.types.relay.Connection): page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") -class EventEdge(sgqlc.types.Type): +class EventEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(Event), graphql_name="node") + + +class ExchangeV2Additions(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("line_items", "subtotal_price_set", "tax_lines", "total_price_set") + line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ExchangeV2LineItem"))), graphql_name="lineItems" + ) + subtotal_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="subtotalPriceSet") + tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TaxLine"))), graphql_name="taxLines") + total_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalPriceSet") + + +class ExchangeV2Connection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ExchangeV2Edge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ExchangeV2"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class ExchangeV2Edge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ExchangeV2"), graphql_name="node") + + +class ExchangeV2LineItem(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ( + "custom_attributes", + "discounted_total_set", + "discounted_unit_price_set", + "fulfillment_service", + "gift_card", + "gift_cards", + "line_item", + "name", + "original_total_set", + "original_unit_price_set", + "quantity", + "requires_shipping", + "sku", + "tax_lines", + "taxable", + "title", + "variant", + "variant_title", + "vendor", + ) + custom_attributes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" + ) + discounted_total_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="discountedTotalSet") + discounted_unit_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="discountedUnitPriceSet") + fulfillment_service = sgqlc.types.Field("FulfillmentService", graphql_name="fulfillmentService") + gift_card = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="giftCard") + gift_cards = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("GiftCard"))), graphql_name="giftCards") + line_item = sgqlc.types.Field("LineItem", graphql_name="lineItem") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + original_total_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="originalTotalSet") + original_unit_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="originalUnitPriceSet") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + requires_shipping = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="requiresShipping") + sku = sgqlc.types.Field(String, graphql_name="sku") + tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TaxLine"))), graphql_name="taxLines") + taxable = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="taxable") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + variant = sgqlc.types.Field("ProductVariant", graphql_name="variant") + variant_title = sgqlc.types.Field(String, graphql_name="variantTitle") + vendor = sgqlc.types.Field(String, graphql_name="vendor") + + +class ExchangeV2Returns(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(Event), graphql_name="node") + __field_names__ = ( + "line_items", + "order_discount_amount_set", + "shipping_refund_amount_set", + "subtotal_price_set", + "tax_lines", + "tip_refund_amount_set", + "total_price_set", + ) + line_items = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ExchangeV2LineItem))), graphql_name="lineItems" + ) + order_discount_amount_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="orderDiscountAmountSet") + shipping_refund_amount_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="shippingRefundAmountSet") + subtotal_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="subtotalPriceSet") + tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TaxLine"))), graphql_name="taxLines") + tip_refund_amount_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="tipRefundAmountSet") + total_price_set = sgqlc.types.Field(sgqlc.types.non_null("MoneyBag"), graphql_name="totalPriceSet") class FailedRequirement(sgqlc.types.Type): @@ -8873,14 +11254,13 @@ class FailedRequirement(sgqlc.types.Type): message = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="message") -class File(sgqlc.types.Interface): +class FileAcknowledgeUpdateFailedPayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("alt", "created_at", "file_errors", "file_status", "preview") - alt = sgqlc.types.Field(String, graphql_name="alt") - created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") - file_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FileError"))), graphql_name="fileErrors") - file_status = sgqlc.types.Field(sgqlc.types.non_null(FileStatus), graphql_name="fileStatus") - preview = sgqlc.types.Field("MediaPreviewImage", graphql_name="preview") + __field_names__ = ("files", "user_errors") + files = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(File)), graphql_name="files") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FilesUserError"))), graphql_name="userErrors" + ) class FileConnection(sgqlc.types.relay.Connection): @@ -8983,6 +11363,13 @@ class FulfillmentEventConnection(sgqlc.types.relay.Connection): page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") +class FulfillmentEventCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_event", "user_errors") + fulfillment_event = sgqlc.types.Field("FulfillmentEvent", graphql_name="fulfillmentEvent") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + + class FulfillmentEventEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") @@ -8992,7 +11379,8 @@ class FulfillmentEventEdge(sgqlc.types.Type): class FulfillmentHold(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("reason", "reason_notes") + __field_names__ = ("held_by", "reason", "reason_notes") + held_by = sgqlc.types.Field(String, graphql_name="heldBy") reason = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentHoldReason), graphql_name="reason") reason_notes = sgqlc.types.Field(String, graphql_name="reasonNotes") @@ -9074,11 +11462,11 @@ class FulfillmentOrderEdge(sgqlc.types.Type): class FulfillmentOrderHoldPayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("fulfillment_order", "user_errors") + __field_names__ = ("fulfillment_order", "remaining_fulfillment_order", "user_errors") fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="fulfillmentOrder") + remaining_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="remainingFulfillmentOrder") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderHoldUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderHoldUserError"))), graphql_name="userErrors" ) @@ -9092,12 +11480,10 @@ class FulfillmentOrderLineItemConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItemEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItemEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItem"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItem"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -9116,6 +11502,15 @@ class FulfillmentOrderLineItemWarning(sgqlc.types.Type): title = sgqlc.types.Field(String, graphql_name="title") +class FulfillmentOrderLineItemsPreparedForPickupPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("user_errors",) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLineItemsPreparedForPickupUserError"))), + graphql_name="userErrors", + ) + + class FulfillmentOrderLocationForMove(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("location", "message", "movable") @@ -9128,12 +11523,10 @@ class FulfillmentOrderLocationForMoveConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLocationForMoveEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderLocationForMoveEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLocationForMove))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLocationForMove))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -9149,12 +11542,10 @@ class FulfillmentOrderMerchantRequestConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMerchantRequestEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMerchantRequestEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMerchantRequest"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMerchantRequest"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -9166,14 +11557,26 @@ class FulfillmentOrderMerchantRequestEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("FulfillmentOrderMerchantRequest"), graphql_name="node") -class FulfillmentOrderMovePayload(sgqlc.types.Type): +class FulfillmentOrderMergePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "moved_fulfillment_order", - "original_fulfillment_order", - "remaining_fulfillment_order", - "user_errors", + __field_names__ = ("fulfillment_order_merges", "user_errors") + fulfillment_order_merges = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMergeResult")), graphql_name="fulfillmentOrderMerges" ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderMergeUserError"))), graphql_name="userErrors" + ) + + +class FulfillmentOrderMergeResult(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order",) + fulfillment_order = sgqlc.types.Field(sgqlc.types.non_null("FulfillmentOrder"), graphql_name="fulfillmentOrder") + + +class FulfillmentOrderMovePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("moved_fulfillment_order", "original_fulfillment_order", "remaining_fulfillment_order", "user_errors") moved_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="movedFulfillmentOrder") original_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="originalFulfillmentOrder") remaining_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="remainingFulfillmentOrder") @@ -9206,8 +11609,7 @@ class FulfillmentOrderReleaseHoldPayload(sgqlc.types.Type): __field_names__ = ("fulfillment_order", "user_errors") fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="fulfillmentOrder") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderReleaseHoldUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderReleaseHoldUserError"))), graphql_name="userErrors" ) @@ -9216,11 +11618,29 @@ class FulfillmentOrderReschedulePayload(sgqlc.types.Type): __field_names__ = ("fulfillment_order", "user_errors") fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="fulfillmentOrder") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderRescheduleUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderRescheduleUserError"))), graphql_name="userErrors" + ) + + +class FulfillmentOrderSplitPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order_splits", "user_errors") + fulfillment_order_splits = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderSplitResult")), graphql_name="fulfillmentOrderSplits" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrderSplitUserError"))), graphql_name="userErrors" ) +class FulfillmentOrderSplitResult(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("fulfillment_order", "remaining_fulfillment_order", "replacement_fulfillment_order") + fulfillment_order = sgqlc.types.Field(sgqlc.types.non_null("FulfillmentOrder"), graphql_name="fulfillmentOrder") + remaining_fulfillment_order = sgqlc.types.Field(sgqlc.types.non_null("FulfillmentOrder"), graphql_name="remainingFulfillmentOrder") + replacement_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="replacementFulfillmentOrder") + + class FulfillmentOrderSubmitCancellationRequestPayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("fulfillment_order", "user_errors") @@ -9230,12 +11650,7 @@ class FulfillmentOrderSubmitCancellationRequestPayload(sgqlc.types.Type): class FulfillmentOrderSubmitFulfillmentRequestPayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "original_fulfillment_order", - "submitted_fulfillment_order", - "unsubmitted_fulfillment_order", - "user_errors", - ) + __field_names__ = ("original_fulfillment_order", "submitted_fulfillment_order", "unsubmitted_fulfillment_order", "user_errors") original_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="originalFulfillmentOrder") submitted_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="submittedFulfillmentOrder") unsubmitted_fulfillment_order = sgqlc.types.Field("FulfillmentOrder", graphql_name="unsubmittedFulfillmentOrder") @@ -9249,6 +11664,15 @@ class FulfillmentOrderSupportedAction(sgqlc.types.Type): external_url = sgqlc.types.Field(URL, graphql_name="externalUrl") +class FulfillmentOrdersReleaseHoldsPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("job", "user_errors") + job = sgqlc.types.Field("Job", graphql_name="job") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("FulfillmentOrdersReleaseHoldsUserError"))), graphql_name="userErrors" + ) + + class FulfillmentOrdersSetFulfillmentDeadlinePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("success", "user_errors") @@ -9282,7 +11706,6 @@ class FulfillmentService(sgqlc.types.Type): "permits_sku_sharing", "product_based", "service_name", - "shipping_methods", "type", ) callback_url = sgqlc.types.Field(URL, graphql_name="callbackUrl") @@ -9294,10 +11717,6 @@ class FulfillmentService(sgqlc.types.Type): permits_sku_sharing = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="permitsSkuSharing") product_based = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="productBased") service_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="serviceName") - shipping_methods = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShippingMethod"))), - graphql_name="shippingMethods", - ) type = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentServiceType), graphql_name="type") @@ -9346,12 +11765,7 @@ class FunctionsAppBridge(sgqlc.types.Type): class FunctionsErrorHistory(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "errors_first_occurred_at", - "first_occurred_at", - "has_been_shared_since_last_error", - "has_shared_recent_errors", - ) + __field_names__ = ("errors_first_occurred_at", "first_occurred_at", "has_been_shared_since_last_error", "has_shared_recent_errors") errors_first_occurred_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="errorsFirstOccurredAt") first_occurred_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="firstOccurredAt") has_been_shared_since_last_error = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="hasBeenSharedSinceLastError") @@ -9397,153 +11811,6 @@ class GiftCardUpdatePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") -class HasEvents(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("events",) - events = sgqlc.types.Field( - sgqlc.types.non_null(EventConnection), - graphql_name="events", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ("sort_key", sgqlc.types.Arg(EventSortKeys, graphql_name="sortKey", default="ID")), - ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), - ) - ), - ) - - -class HasLocalizationExtensions(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("localization_extensions",) - localization_extensions = sgqlc.types.Field( - sgqlc.types.non_null("LocalizationExtensionConnection"), - graphql_name="localizationExtensions", - args=sgqlc.types.ArgDict( - ( - ( - "country_codes", - sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(CountryCode)), - graphql_name="countryCodes", - default=None, - ), - ), - ( - "purposes", - sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(LocalizationExtensionPurpose)), - graphql_name="purposes", - default=None, - ), - ), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - - -class HasMetafieldDefinitions(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("metafield_definitions",) - metafield_definitions = sgqlc.types.Field( - sgqlc.types.non_null("MetafieldDefinitionConnection"), - graphql_name="metafieldDefinitions", - args=sgqlc.types.ArgDict( - ( - ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), - ( - "pinned_status", - sgqlc.types.Arg(MetafieldDefinitionPinnedStatus, graphql_name="pinnedStatus", default="ANY"), - ), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ("sort_key", sgqlc.types.Arg(MetafieldDefinitionSortKeys, graphql_name="sortKey", default="ID")), - ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), - ) - ), - ) - - -class HasMetafields(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("metafield", "metafields", "private_metafield", "private_metafields") - metafield = sgqlc.types.Field( - "Metafield", - graphql_name="metafield", - args=sgqlc.types.ArgDict( - ( - ("namespace", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="namespace", default=None)), - ("key", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="key", default=None)), - ) - ), - ) - metafields = sgqlc.types.Field( - sgqlc.types.non_null("MetafieldConnection"), - graphql_name="metafields", - args=sgqlc.types.ArgDict( - ( - ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - private_metafield = sgqlc.types.Field( - "PrivateMetafield", - graphql_name="privateMetafield", - args=sgqlc.types.ArgDict( - ( - ("namespace", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="namespace", default=None)), - ("key", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="key", default=None)), - ) - ), - ) - private_metafields = sgqlc.types.Field( - sgqlc.types.non_null("PrivateMetafieldConnection"), - graphql_name="privateMetafields", - args=sgqlc.types.ArgDict( - ( - ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - - -class HasPublishedTranslations(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("translations",) - translations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublishedTranslation"))), - graphql_name="translations", - args=sgqlc.types.ArgDict( - ( - ("locale", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="locale", default=None)), - ("market_id", sgqlc.types.Arg(ID, graphql_name="marketId", default=None)), - ) - ), - ) - - class ImageConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -9573,6 +11840,15 @@ class InventoryActivatePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class InventoryAdjustQuantitiesPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("inventory_adjustment_group", "user_errors") + inventory_adjustment_group = sgqlc.types.Field("InventoryAdjustmentGroup", graphql_name="inventoryAdjustmentGroup") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryAdjustQuantitiesUserError"))), graphql_name="userErrors" + ) + + class InventoryAdjustQuantityPayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("inventory_level", "user_errors") @@ -9593,11 +11869,21 @@ class InventoryBulkToggleActivationPayload(sgqlc.types.Type): inventory_item = sgqlc.types.Field("InventoryItem", graphql_name="inventoryItem") inventory_levels = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("InventoryLevel")), graphql_name="inventoryLevels") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryBulkToggleActivationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryBulkToggleActivationUserError"))), graphql_name="userErrors" ) +class InventoryChange(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("delta", "item", "ledger_document_uri", "location", "name", "quantity_after_change") + delta = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="delta") + item = sgqlc.types.Field("InventoryItem", graphql_name="item") + ledger_document_uri = sgqlc.types.Field(String, graphql_name="ledgerDocumentUri") + location = sgqlc.types.Field("Location", graphql_name="location") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + quantity_after_change = sgqlc.types.Field(Int, graphql_name="quantityAfterChange") + + class InventoryDeactivatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("user_errors",) @@ -9634,11 +11920,55 @@ class InventoryLevelConnection(sgqlc.types.relay.Connection): page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") -class InventoryLevelEdge(sgqlc.types.Type): +class InventoryLevelEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("InventoryLevel"), graphql_name="node") + + +class InventoryMoveQuantitiesPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("inventory_adjustment_group", "user_errors") + inventory_adjustment_group = sgqlc.types.Field("InventoryAdjustmentGroup", graphql_name="inventoryAdjustmentGroup") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryMoveQuantitiesUserError"))), graphql_name="userErrors" + ) + + +class InventoryProperties(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("quantity_names",) + quantity_names = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventoryQuantityName"))), graphql_name="quantityNames" + ) + + +class InventoryQuantity(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("name", "quantity", "updated_at") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + updated_at = sgqlc.types.Field(DateTime, graphql_name="updatedAt") + + +class InventoryQuantityName(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("InventoryLevel"), graphql_name="node") + __field_names__ = ("belongs_to", "comprises", "display_name", "is_in_use", "name") + belongs_to = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="belongsTo") + comprises = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="comprises") + display_name = sgqlc.types.Field(String, graphql_name="displayName") + is_in_use = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isInUse") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + + +class InventorySetOnHandQuantitiesPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("inventory_adjustment_group", "user_errors") + inventory_adjustment_group = sgqlc.types.Field("InventoryAdjustmentGroup", graphql_name="inventoryAdjustmentGroup") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("InventorySetOnHandQuantitiesUserError"))), graphql_name="userErrors" + ) class Job(sgqlc.types.Type): @@ -9649,12 +11979,6 @@ class Job(sgqlc.types.Type): query = sgqlc.types.Field("QueryRoot", graphql_name="query") -class LegacyInteroperability(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("legacy_resource_id",) - legacy_resource_id = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="legacyResourceId") - - class LimitedPendingOrderCount(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("at_max", "count") @@ -9677,6 +12001,14 @@ class LineItemEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("LineItem"), graphql_name="node") +class LineItemGroup(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("id", "quantity", "title") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + class LineItemMutableConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -9720,8 +12052,7 @@ class LocalizationExtensionConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocalizationExtensionEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocalizationExtensionEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(LocalizationExtension))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") @@ -9749,8 +12080,7 @@ class LocationAddPayload(sgqlc.types.Type): __field_names__ = ("location", "user_errors") location = sgqlc.types.Field("Location", graphql_name="location") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationAddUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationAddUserError"))), graphql_name="userErrors" ) @@ -9807,8 +12137,7 @@ class LocationDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_location_id", "location_delete_user_errors") deleted_location_id = sgqlc.types.Field(ID, graphql_name="deletedLocationId") location_delete_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationDeleteUserError"))), - graphql_name="locationDeleteUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationDeleteUserError"))), graphql_name="locationDeleteUserErrors" ) @@ -9824,24 +12153,33 @@ class LocationEditPayload(sgqlc.types.Type): __field_names__ = ("location", "user_errors") location = sgqlc.types.Field("Location", graphql_name="location") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationEditUserError"))), + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("LocationEditUserError"))), graphql_name="userErrors" + ) + + +class LocationLocalPickupDisablePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("location_id", "user_errors") + location_id = sgqlc.types.Field(ID, graphql_name="locationId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryLocationLocalPickupSettingsError"))), graphql_name="userErrors", ) -class LocationSuggestedAddress(sgqlc.types.Type): +class LocationLocalPickupEnablePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "address1", - "address2", - "city", - "country", - "country_code", - "formatted", - "province", - "province_code", - "zip", + __field_names__ = ("local_pickup_settings", "user_errors") + local_pickup_settings = sgqlc.types.Field(DeliveryLocalPickupSettings, graphql_name="localPickupSettings") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("DeliveryLocationLocalPickupSettingsError"))), + graphql_name="userErrors", ) + + +class LocationSuggestedAddress(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("address1", "address2", "city", "country", "country_code", "formatted", "province", "province_code", "zip") address1 = sgqlc.types.Field(String, graphql_name="address1") address2 = sgqlc.types.Field(String, graphql_name="address2") city = sgqlc.types.Field(String, graphql_name="city") @@ -9853,6 +12191,36 @@ class LocationSuggestedAddress(sgqlc.types.Type): zip = sgqlc.types.Field(String, graphql_name="zip") +class MailingAddressConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MailingAddressEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MailingAddress"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class MailingAddressEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("MailingAddress"), graphql_name="node") + + +class MarketCatalogConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketCatalogEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketCatalog"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class MarketCatalogEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("MarketCatalog"), graphql_name="node") + + class MarketConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -9882,8 +12250,7 @@ class MarketCurrencySettingsUpdatePayload(sgqlc.types.Type): __field_names__ = ("market", "user_errors") market = sgqlc.types.Field("Market", graphql_name="market") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketCurrencySettingsUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketCurrencySettingsUserError"))), graphql_name="userErrors" ) @@ -9915,8 +12282,7 @@ class MarketLocalizableResource(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("market_localizable_content", "market_localizations", "resource_id") market_localizable_content = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MarketLocalizableContent))), - graphql_name="marketLocalizableContent", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MarketLocalizableContent))), graphql_name="marketLocalizableContent" ) market_localizations = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketLocalization"))), @@ -9930,8 +12296,7 @@ class MarketLocalizableResourceConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketLocalizableResourceEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketLocalizableResourceEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MarketLocalizableResource))), graphql_name="nodes" @@ -9948,10 +12313,11 @@ class MarketLocalizableResourceEdge(sgqlc.types.Type): class MarketLocalization(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("key", "market", "outdated", "value") + __field_names__ = ("key", "market", "outdated", "updated_at", "value") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") market = sgqlc.types.Field(sgqlc.types.non_null("Market"), graphql_name="market") outdated = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="outdated") + updated_at = sgqlc.types.Field(DateTime, graphql_name="updatedAt") value = sgqlc.types.Field(String, graphql_name="value") @@ -9962,8 +12328,7 @@ class MarketLocalizationsRegisterPayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null(MarketLocalization)), graphql_name="marketLocalizations" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), graphql_name="userErrors" ) @@ -9974,18 +12339,10 @@ class MarketLocalizationsRemovePayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null(MarketLocalization)), graphql_name="marketLocalizations" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), graphql_name="userErrors" ) -class MarketRegion(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("id", "name") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - - class MarketRegionConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -10079,8 +12436,7 @@ class MarketingActivityCreateExternalPayload(sgqlc.types.Type): __field_names__ = ("marketing_activity", "user_errors") marketing_activity = sgqlc.types.Field("MarketingActivity", graphql_name="marketingActivity") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketingActivityUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketingActivityUserError"))), graphql_name="userErrors" ) @@ -10111,8 +12467,7 @@ class MarketingActivityUpdateExternalPayload(sgqlc.types.Type): __field_names__ = ("marketing_activity", "user_errors") marketing_activity = sgqlc.types.Field("MarketingActivity", graphql_name="marketingActivity") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketingActivityUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketingActivityUserError"))), graphql_name="userErrors" ) @@ -10195,21 +12550,6 @@ class MarketingEventEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("MarketingEvent"), graphql_name="node") -class Media(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("alt", "media_content_type", "media_errors", "media_warnings", "preview", "status") - alt = sgqlc.types.Field(String, graphql_name="alt") - media_content_type = sgqlc.types.Field(sgqlc.types.non_null(MediaContentType), graphql_name="mediaContentType") - media_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaError"))), graphql_name="mediaErrors" - ) - media_warnings = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaWarning"))), graphql_name="mediaWarnings" - ) - preview = sgqlc.types.Field("MediaPreviewImage", graphql_name="preview") - status = sgqlc.types.Field(sgqlc.types.non_null(MediaStatus), graphql_name="status") - - class MediaConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -10255,9 +12595,16 @@ class MediaWarning(sgqlc.types.Type): class MerchantApprovalSignals(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("identity_verified", "verified_by_shopify") + __field_names__ = ("identity_verified", "verified_by_shopify", "verified_by_shopify_tier") identity_verified = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="identityVerified") verified_by_shopify = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="verifiedByShopify") + verified_by_shopify_tier = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="verifiedByShopifyTier") + + +class MetafieldAccess(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("admin",) + admin = sgqlc.types.Field(MetafieldAdminAccess, graphql_name="admin") class MetafieldConnection(sgqlc.types.relay.Connection): @@ -10283,8 +12630,7 @@ class MetafieldDefinitionCreatePayload(sgqlc.types.Type): __field_names__ = ("created_definition", "user_errors") created_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="createdDefinition") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionCreateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionCreateUserError"))), graphql_name="userErrors" ) @@ -10293,8 +12639,7 @@ class MetafieldDefinitionDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_definition_id", "user_errors") deleted_definition_id = sgqlc.types.Field(ID, graphql_name="deletedDefinitionId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionDeleteUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionDeleteUserError"))), graphql_name="userErrors" ) @@ -10305,136 +12650,335 @@ class MetafieldDefinitionEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("MetafieldDefinition"), graphql_name="node") -class MetafieldDefinitionPinPayload(sgqlc.types.Type): +class MetafieldDefinitionPinPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("pinned_definition", "user_errors") + pinned_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="pinnedDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionPinUserError"))), graphql_name="userErrors" + ) + + +class MetafieldDefinitionSupportedValidation(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("name", "type") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + + +class MetafieldDefinitionType(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("category", "name", "supported_validations", "supports_definition_migrations") + category = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="category") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + supported_validations = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionSupportedValidation))), + graphql_name="supportedValidations", + ) + supports_definition_migrations = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supportsDefinitionMigrations") + + +class MetafieldDefinitionUnpinPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("unpinned_definition", "user_errors") + unpinned_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="unpinnedDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionUnpinUserError"))), graphql_name="userErrors" + ) + + +class MetafieldDefinitionUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("updated_definition", "user_errors", "validation_job") + updated_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="updatedDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionUpdateUserError"))), graphql_name="userErrors" + ) + validation_job = sgqlc.types.Field(Job, graphql_name="validationJob") + + +class MetafieldDefinitionValidation(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("name", "type", "value") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + value = sgqlc.types.Field(String, graphql_name="value") + + +class MetafieldDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + + +class MetafieldEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("Metafield"), graphql_name="node") + + +class MetafieldReferenceConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldReferenceEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of("MetafieldReference")), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class MetafieldReferenceEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field("MetafieldReference", graphql_name="node") + + +class MetafieldRelation(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("key", "name", "namespace", "referencer", "target") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + namespace = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="namespace") + referencer = sgqlc.types.Field(sgqlc.types.non_null("MetafieldReferencer"), graphql_name="referencer") + target = sgqlc.types.Field(sgqlc.types.non_null("MetafieldReference"), graphql_name="target") + + +class MetafieldRelationConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldRelationEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldRelation))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class MetafieldRelationEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(MetafieldRelation), graphql_name="node") + + +class MetafieldStorefrontVisibilityConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldStorefrontVisibilityEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldStorefrontVisibility"))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + + +class MetafieldStorefrontVisibilityCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("metafield_storefront_visibility", "user_errors") + metafield_storefront_visibility = sgqlc.types.Field("MetafieldStorefrontVisibility", graphql_name="metafieldStorefrontVisibility") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + + +class MetafieldStorefrontVisibilityDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_metafield_storefront_visibility_id", "user_errors") + deleted_metafield_storefront_visibility_id = sgqlc.types.Field(ID, graphql_name="deletedMetafieldStorefrontVisibilityId") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + + +class MetafieldStorefrontVisibilityEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("MetafieldStorefrontVisibility"), graphql_name="node") + + +class MetafieldsSetPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("metafields", "user_errors") + metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("Metafield")), graphql_name="metafields") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldsSetUserError"))), graphql_name="userErrors" + ) + + +class MetaobjectAccess(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("admin", "storefront") + admin = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectAdminAccess), graphql_name="admin") + storefront = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectStorefrontAccess), graphql_name="storefront") + + +class MetaobjectBulkDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("job", "user_errors") + job = sgqlc.types.Field(Job, graphql_name="job") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) + + +class MetaobjectCapabilities(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("publishable", "translatable") + publishable = sgqlc.types.Field(sgqlc.types.non_null("MetaobjectCapabilitiesPublishable"), graphql_name="publishable") + translatable = sgqlc.types.Field(sgqlc.types.non_null("MetaobjectCapabilitiesTranslatable"), graphql_name="translatable") + + +class MetaobjectCapabilitiesPublishable(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("enabled",) + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") + + +class MetaobjectCapabilitiesTranslatable(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("enabled",) + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") + + +class MetaobjectCapabilityData(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("pinned_definition", "user_errors") - pinned_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="pinnedDefinition") - user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionPinUserError"))), - graphql_name="userErrors", - ) + __field_names__ = ("publishable",) + publishable = sgqlc.types.Field("MetaobjectCapabilityDataPublishable", graphql_name="publishable") -class MetafieldDefinitionSupportedValidation(sgqlc.types.Type): +class MetaobjectCapabilityDataPublishable(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("name", "type") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + __field_names__ = ("status",) + status = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectStatus), graphql_name="status") -class MetafieldDefinitionType(sgqlc.types.Type): +class MetaobjectConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema - __field_names__ = ("category", "name", "supported_validations", "supports_definition_migrations") - category = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="category") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - supported_validations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionSupportedValidation))), - graphql_name="supportedValidations", - ) - supports_definition_migrations = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supportsDefinitionMigrations") + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Metaobject"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") -class MetafieldDefinitionUnpinPayload(sgqlc.types.Type): +class MetaobjectCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("unpinned_definition", "user_errors") - unpinned_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="unpinnedDefinition") + __field_names__ = ("metaobject", "user_errors") + metaobject = sgqlc.types.Field("Metaobject", graphql_name="metaobject") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionUnpinUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" ) -class MetafieldDefinitionUpdatePayload(sgqlc.types.Type): +class MetaobjectDefinitionConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema - __field_names__ = ("updated_definition", "user_errors") - updated_definition = sgqlc.types.Field("MetafieldDefinition", graphql_name="updatedDefinition") - user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldDefinitionUpdateUserError"))), - graphql_name="userErrors", + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectDefinitionEdge"))), graphql_name="edges" ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectDefinition"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") -class MetafieldDefinitionValidation(sgqlc.types.Type): +class MetaobjectDefinitionCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("name", "type", "value") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") - value = sgqlc.types.Field(String, graphql_name="value") + __field_names__ = ("metaobject_definition", "user_errors") + metaobject_definition = sgqlc.types.Field("MetaobjectDefinition", graphql_name="metaobjectDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) -class MetafieldDeletePayload(sgqlc.types.Type): +class MetaobjectDefinitionDeletePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("deleted_id", "user_errors") deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) -class MetafieldEdge(sgqlc.types.Type): +class MetaobjectDefinitionEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("Metafield"), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null("MetaobjectDefinition"), graphql_name="node") -class MetafieldReferenceConnection(sgqlc.types.relay.Connection): +class MetaobjectDefinitionUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldReferenceEdge"))), graphql_name="edges" + __field_names__ = ("metaobject_definition", "user_errors") + metaobject_definition = sgqlc.types.Field("MetaobjectDefinition", graphql_name="metaobjectDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" ) - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of("MetafieldReference")), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") -class MetafieldReferenceEdge(sgqlc.types.Type): +class MetaobjectDeletePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field("MetafieldReference", graphql_name="node") + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) -class MetafieldStorefrontVisibilityConnection(sgqlc.types.relay.Connection): +class MetaobjectEdge(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldStorefrontVisibilityEdge"))), - graphql_name="edges", - ) - nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldStorefrontVisibility"))), - graphql_name="nodes", - ) - page_info = sgqlc.types.Field(sgqlc.types.non_null("PageInfo"), graphql_name="pageInfo") + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("Metaobject"), graphql_name="node") -class MetafieldStorefrontVisibilityCreatePayload(sgqlc.types.Type): +class MetaobjectField(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("metafield_storefront_visibility", "user_errors") - metafield_storefront_visibility = sgqlc.types.Field("MetafieldStorefrontVisibility", graphql_name="metafieldStorefrontVisibility") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + __field_names__ = ("definition", "key", "reference", "references", "type", "value") + definition = sgqlc.types.Field(sgqlc.types.non_null("MetaobjectFieldDefinition"), graphql_name="definition") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + reference = sgqlc.types.Field("MetafieldReference", graphql_name="reference") + references = sgqlc.types.Field( + MetafieldReferenceConnection, + graphql_name="references", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ) + ), + ) + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + value = sgqlc.types.Field(String, graphql_name="value") -class MetafieldStorefrontVisibilityDeletePayload(sgqlc.types.Type): +class MetaobjectFieldDefinition(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("deleted_metafield_storefront_visibility_id", "user_errors") - deleted_metafield_storefront_visibility_id = sgqlc.types.Field(ID, graphql_name="deletedMetafieldStorefrontVisibilityId") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + __field_names__ = ("description", "key", "name", "required", "type", "validations") + description = sgqlc.types.Field(String, graphql_name="description") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + required = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="required") + type = sgqlc.types.Field(sgqlc.types.non_null(MetafieldDefinitionType), graphql_name="type") + validations = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidation))), graphql_name="validations" + ) -class MetafieldStorefrontVisibilityEdge(sgqlc.types.Type): +class MetaobjectUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("MetafieldStorefrontVisibility"), graphql_name="node") + __field_names__ = ("metaobject", "user_errors") + metaobject = sgqlc.types.Field("Metaobject", graphql_name="metaobject") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) -class MetafieldsSetPayload(sgqlc.types.Type): +class MetaobjectUpsertPayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("metafields", "user_errors") - metafields = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("Metafield")), graphql_name="metafields") + __field_names__ = ("metaobject", "user_errors") + metaobject = sgqlc.types.Field("Metaobject", graphql_name="metaobject") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetafieldsSetUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" ) @@ -10470,10 +13014,8 @@ class MoneyV2(sgqlc.types.Type): class Mutation(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( - "app_credit_create", + "abandonment_update_activities_delivery_statuses", "app_purchase_one_time_create", - "app_revenue_attribution_record_create", - "app_revenue_attribution_record_delete", "app_subscription_cancel", "app_subscription_create", "app_subscription_line_item_update", @@ -10483,6 +13025,12 @@ class Mutation(sgqlc.types.Type): "bulk_operation_run_mutation", "bulk_operation_run_query", "bulk_product_resource_feedback_create", + "cart_transform_create", + "cart_transform_delete", + "catalog_context_update", + "catalog_create", + "catalog_delete", + "catalog_update", "collection_add_products", "collection_add_products_v2", "collection_create", @@ -10498,8 +13046,10 @@ class Mutation(sgqlc.types.Type): "company_contact_assign_roles", "company_contact_create", "company_contact_delete", + "company_contact_remove_from_company", "company_contact_revoke_role", "company_contact_revoke_roles", + "company_contact_send_welcome_email", "company_contact_update", "company_contacts_delete", "company_create", @@ -10522,8 +13072,11 @@ class Mutation(sgqlc.types.Type): "customer_delete", "customer_email_marketing_consent_update", "customer_generate_account_activation_url", + "customer_merge", + "customer_payment_method_create_from_duplication_data", "customer_payment_method_credit_card_create", "customer_payment_method_credit_card_update", + "customer_payment_method_get_duplication_data", "customer_payment_method_get_update_url", "customer_payment_method_paypal_billing_agreement_create", "customer_payment_method_paypal_billing_agreement_update", @@ -10532,10 +13085,16 @@ class Mutation(sgqlc.types.Type): "customer_payment_method_send_update_email", "customer_remove_tax_exemptions", "customer_replace_tax_exemptions", + "customer_segment_members_query_create", "customer_sms_marketing_consent_update", "customer_update", "customer_update_default_address", "delegate_access_token_create", + "delegate_access_token_destroy", + "delivery_customization_activation", + "delivery_customization_create", + "delivery_customization_delete", + "delivery_customization_update", "delivery_profile_create", "delivery_profile_remove", "delivery_profile_update", @@ -10581,27 +13140,34 @@ class Mutation(sgqlc.types.Type): "draft_order_invoice_preview", "draft_order_invoice_send", "draft_order_update", + "event_bridge_server_pixel_update", "event_bridge_webhook_subscription_create", "event_bridge_webhook_subscription_update", + "file_acknowledge_update_failed", "file_create", "file_delete", "file_update", "flow_trigger_receive", "fulfillment_cancel", "fulfillment_create_v2", + "fulfillment_event_create", "fulfillment_order_accept_cancellation_request", "fulfillment_order_accept_fulfillment_request", "fulfillment_order_cancel", "fulfillment_order_close", "fulfillment_order_hold", + "fulfillment_order_line_items_prepared_for_pickup", + "fulfillment_order_merge", "fulfillment_order_move", "fulfillment_order_open", "fulfillment_order_reject_cancellation_request", "fulfillment_order_reject_fulfillment_request", "fulfillment_order_release_hold", "fulfillment_order_reschedule", + "fulfillment_order_split", "fulfillment_order_submit_cancellation_request", "fulfillment_order_submit_fulfillment_request", + "fulfillment_orders_release_holds", "fulfillment_orders_set_fulfillment_deadline", "fulfillment_service_create", "fulfillment_service_delete", @@ -10611,16 +13177,19 @@ class Mutation(sgqlc.types.Type): "gift_card_disable", "gift_card_update", "inventory_activate", - "inventory_adjust_quantity", - "inventory_bulk_adjust_quantity_at_location", + "inventory_adjust_quantities", "inventory_bulk_toggle_activation", "inventory_deactivate", "inventory_item_update", + "inventory_move_quantities", + "inventory_set_on_hand_quantities", "location_activate", "location_add", "location_deactivate", "location_delete", "location_edit", + "location_local_pickup_disable", + "location_local_pickup_enable", "market_create", "market_currency_settings_update", "market_delete", @@ -10643,9 +13212,15 @@ class Mutation(sgqlc.types.Type): "metafield_definition_unpin", "metafield_definition_update", "metafield_delete", - "metafield_storefront_visibility_create", - "metafield_storefront_visibility_delete", "metafields_set", + "metaobject_bulk_delete", + "metaobject_create", + "metaobject_definition_create", + "metaobject_definition_delete", + "metaobject_definition_update", + "metaobject_delete", + "metaobject_update", + "metaobject_upsert", "order_capture", "order_close", "order_create_mandate_payment", @@ -10660,35 +13235,34 @@ class Mutation(sgqlc.types.Type): "order_mark_as_paid", "order_open", "order_update", + "payment_customization_activation", + "payment_customization_create", + "payment_customization_delete", + "payment_customization_update", + "payment_reminder_send", "payment_terms_create", "payment_terms_delete", "payment_terms_update", "price_list_create", "price_list_delete", "price_list_fixed_prices_add", + "price_list_fixed_prices_by_product_update", "price_list_fixed_prices_delete", + "price_list_fixed_prices_update", "price_list_update", - "price_rule_activate", - "price_rule_create", - "price_rule_deactivate", - "price_rule_delete", - "price_rule_discount_code_create", - "price_rule_discount_code_update", - "price_rule_update", - "private_metafield_delete", - "private_metafield_upsert", - "product_append_images", "product_change_status", "product_create", "product_create_media", "product_delete", - "product_delete_images", + "product_delete_async", "product_delete_media", "product_duplicate", - "product_image_update", + "product_duplicate_async_v2", + "product_feed_create", + "product_feed_delete", + "product_full_sync", "product_join_selling_plan_groups", "product_leave_selling_plan_groups", - "product_reorder_images", "product_reorder_media", "product_update", "product_update_media", @@ -10698,18 +13272,36 @@ class Mutation(sgqlc.types.Type): "product_variant_detach_media", "product_variant_join_selling_plan_groups", "product_variant_leave_selling_plan_groups", + "product_variant_relationship_bulk_update", "product_variant_update", "product_variants_bulk_create", "product_variants_bulk_delete", "product_variants_bulk_reorder", "product_variants_bulk_update", + "pub_sub_server_pixel_update", "pub_sub_webhook_subscription_create", "pub_sub_webhook_subscription_update", + "publication_create", + "publication_delete", + "publication_update", "publishable_publish", "publishable_publish_to_current_channel", "publishable_unpublish", "publishable_unpublish_to_current_channel", + "quantity_rules_add", + "quantity_rules_delete", "refund_create", + "return_approve_request", + "return_cancel", + "return_close", + "return_create", + "return_decline_request", + "return_refund", + "return_reopen", + "return_request", + "reverse_delivery_create_with_shipping", + "reverse_delivery_shipping_update", + "reverse_fulfillment_order_dispose", "saved_search_create", "saved_search_delete", "saved_search_update", @@ -10726,6 +13318,8 @@ class Mutation(sgqlc.types.Type): "selling_plan_group_remove_product_variants", "selling_plan_group_remove_products", "selling_plan_group_update", + "server_pixel_create", + "server_pixel_delete", "shipping_package_delete", "shipping_package_make_default", "shipping_package_update", @@ -10733,8 +13327,10 @@ class Mutation(sgqlc.types.Type): "shop_locale_enable", "shop_locale_update", "shop_policy_update", + "shop_resource_feedback_create", "staged_uploads_create", "standard_metafield_definition_enable", + "standard_metaobject_definition_enable", "storefront_access_token_create", "storefront_access_token_delete", "subscription_billing_attempt_create", @@ -10744,7 +13340,9 @@ class Mutation(sgqlc.types.Type): "subscription_billing_cycle_edit_delete", "subscription_billing_cycle_edits_delete", "subscription_billing_cycle_schedule_edit", + "subscription_contract_atomic_create", "subscription_contract_create", + "subscription_contract_product_change", "subscription_contract_set_next_billing_date", "subscription_contract_update", "subscription_draft_commit", @@ -10760,6 +13358,7 @@ class Mutation(sgqlc.types.Type): "subscription_draft_update", "tags_add", "tags_remove", + "tax_app_configure", "translations_register", "translations_remove", "url_redirect_bulk_delete_all", @@ -10778,17 +13377,19 @@ class Mutation(sgqlc.types.Type): "webhook_subscription_delete", "webhook_subscription_update", ) - app_credit_create = sgqlc.types.Field( - AppCreditCreatePayload, - graphql_name="appCreditCreate", + abandonment_update_activities_delivery_statuses = sgqlc.types.Field( + AbandonmentUpdateActivitiesDeliveryStatusesPayload, + graphql_name="abandonmentUpdateActivitiesDeliveryStatuses", args=sgqlc.types.ArgDict( ( + ("abandonment_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="abandonmentId", default=None)), + ("marketing_activity_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="marketingActivityId", default=None)), ( - "description", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="description", default=None), + "delivery_status", + sgqlc.types.Arg(sgqlc.types.non_null(AbandonmentDeliveryState), graphql_name="deliveryStatus", default=None), ), - ("amount", sgqlc.types.Arg(sgqlc.types.non_null(MoneyInput), graphql_name="amount", default=None)), - ("test", sgqlc.types.Arg(Boolean, graphql_name="test", default=False)), + ("delivered_at", sgqlc.types.Arg(DateTime, graphql_name="deliveredAt", default=None)), + ("delivery_status_change_reason", sgqlc.types.Arg(String, graphql_name="deliveryStatusChangeReason", default=None)), ) ), ) @@ -10804,27 +13405,6 @@ class Mutation(sgqlc.types.Type): ) ), ) - app_revenue_attribution_record_create = sgqlc.types.Field( - AppRevenueAttributionRecordCreatePayload, - graphql_name="appRevenueAttributionRecordCreate", - args=sgqlc.types.ArgDict( - ( - ( - "app_revenue_attribution_record", - sgqlc.types.Arg( - sgqlc.types.non_null(AppRevenueAttributionRecordInput), - graphql_name="appRevenueAttributionRecord", - default=None, - ), - ), - ) - ), - ) - app_revenue_attribution_record_delete = sgqlc.types.Field( - AppRevenueAttributionRecordDeletePayload, - graphql_name="appRevenueAttributionRecordDelete", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) app_subscription_cancel = sgqlc.types.Field( AppSubscriptionCancelPayload, graphql_name="appSubscriptionCancel", @@ -10865,10 +13445,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "capped_amount", - sgqlc.types.Arg(sgqlc.types.non_null(MoneyInput), graphql_name="cappedAmount", default=None), - ), + ("capped_amount", sgqlc.types.Arg(sgqlc.types.non_null(MoneyInput), graphql_name="cappedAmount", default=None)), ) ), ) @@ -10892,10 +13469,8 @@ class Mutation(sgqlc.types.Type): sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="subscriptionLineItemId", default=None), ), ("price", sgqlc.types.Arg(sgqlc.types.non_null(MoneyInput), graphql_name="price", default=None)), - ( - "description", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="description", default=None), - ), + ("description", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="description", default=None)), + ("idempotency_key", sgqlc.types.Arg(String, graphql_name="idempotencyKey", default=None)), ) ), ) @@ -10910,10 +13485,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("mutation", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="mutation", default=None)), - ( - "staged_upload_path", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="stagedUploadPath", default=None), - ), + ("staged_upload_path", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="stagedUploadPath", default=None)), ("client_identifier", sgqlc.types.Arg(String, graphql_name="clientIdentifier", default=None)), ) ), @@ -10939,6 +13511,56 @@ class Mutation(sgqlc.types.Type): ) ), ) + cart_transform_create = sgqlc.types.Field( + CartTransformCreatePayload, + graphql_name="cartTransformCreate", + args=sgqlc.types.ArgDict( + (("function_id", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="functionId", default=None)),) + ), + ) + cart_transform_delete = sgqlc.types.Field( + CartTransformDeletePayload, + graphql_name="cartTransformDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + catalog_context_update = sgqlc.types.Field( + CatalogContextUpdatePayload, + graphql_name="catalogContextUpdate", + args=sgqlc.types.ArgDict( + ( + ("catalog_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="catalogId", default=None)), + ("contexts_to_add", sgqlc.types.Arg(CatalogContextInput, graphql_name="contextsToAdd", default=None)), + ("contexts_to_remove", sgqlc.types.Arg(CatalogContextInput, graphql_name="contextsToRemove", default=None)), + ) + ), + ) + catalog_create = sgqlc.types.Field( + CatalogCreatePayload, + graphql_name="catalogCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(CatalogCreateInput), graphql_name="input", default=None)),) + ), + ) + catalog_delete = sgqlc.types.Field( + CatalogDeletePayload, + graphql_name="catalogDelete", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("delete_dependent_resources", sgqlc.types.Arg(Boolean, graphql_name="deleteDependentResources", default=False)), + ) + ), + ) + catalog_update = sgqlc.types.Field( + CatalogUpdatePayload, + graphql_name="catalogUpdate", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(CatalogUpdateInput), graphql_name="input", default=None)), + ) + ), + ) collection_add_products = sgqlc.types.Field( CollectionAddProductsPayload, graphql_name="collectionAddProducts", @@ -10948,9 +13570,7 @@ class Mutation(sgqlc.types.Type): ( "product_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productIds", default=None ), ), ) @@ -10965,9 +13585,7 @@ class Mutation(sgqlc.types.Type): ( "product_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productIds", default=None ), ), ) @@ -10982,12 +13600,7 @@ class Mutation(sgqlc.types.Type): CollectionDeletePayload, graphql_name="collectionDelete", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CollectionDeleteInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(CollectionDeleteInput), graphql_name="input", default=None)),) ), ) collection_remove_products = sgqlc.types.Field( @@ -10999,9 +13612,7 @@ class Mutation(sgqlc.types.Type): ( "product_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productIds", default=None ), ), ) @@ -11016,9 +13627,7 @@ class Mutation(sgqlc.types.Type): ( "moves", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MoveInput))), - graphql_name="moves", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MoveInput))), graphql_name="moves", default=None ), ), ) @@ -11037,9 +13646,7 @@ class Mutation(sgqlc.types.Type): ( "company_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="companyIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="companyIds", default=None ), ), ) @@ -11066,10 +13673,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("company_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyId", default=None)), - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), ) ), ) @@ -11078,18 +13682,9 @@ class Mutation(sgqlc.types.Type): graphql_name="companyContactAssignRole", args=sgqlc.types.ArgDict( ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), - ( - "company_contact_role_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactRoleId", default=None), - ), - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), + ("company_contact_role_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactRoleId", default=None)), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), ) ), ) @@ -11098,10 +13693,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyContactAssignRoles", args=sgqlc.types.ArgDict( ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), ( "roles_to_assign", sgqlc.types.Arg( @@ -11119,10 +13711,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("company_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CompanyContactInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(CompanyContactInput), graphql_name="input", default=None)), ) ), ) @@ -11130,12 +13719,14 @@ class Mutation(sgqlc.types.Type): CompanyContactDeletePayload, graphql_name="companyContactDelete", args=sgqlc.types.ArgDict( - ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), - ) + (("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)),) + ), + ) + company_contact_remove_from_company = sgqlc.types.Field( + CompanyContactRemoveFromCompanyPayload, + graphql_name="companyContactRemoveFromCompany", + args=sgqlc.types.ArgDict( + (("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)),) ), ) company_contact_revoke_role = sgqlc.types.Field( @@ -11143,10 +13734,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyContactRevokeRole", args=sgqlc.types.ArgDict( ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), ( "company_contact_role_assignment_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactRoleAssignmentId", default=None), @@ -11159,10 +13747,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyContactRevokeRoles", args=sgqlc.types.ArgDict( ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), ( "role_assignment_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="roleAssignmentIds", default=None), @@ -11171,19 +13756,23 @@ class Mutation(sgqlc.types.Type): ) ), ) + company_contact_send_welcome_email = sgqlc.types.Field( + CompanyContactSendWelcomeEmailPayload, + graphql_name="companyContactSendWelcomeEmail", + args=sgqlc.types.ArgDict( + ( + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), + ("email", sgqlc.types.Arg(EmailInput, graphql_name="email", default=None)), + ) + ), + ) company_contact_update = sgqlc.types.Field( CompanyContactUpdatePayload, graphql_name="companyContactUpdate", args=sgqlc.types.ArgDict( ( - ( - "company_contact_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None), - ), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CompanyContactInput), graphql_name="input", default=None), - ), + ("company_contact_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyContactId", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(CompanyContactInput), graphql_name="input", default=None)), ) ), ) @@ -11195,9 +13784,7 @@ class Mutation(sgqlc.types.Type): ( "company_contact_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="companyContactIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="companyContactIds", default=None ), ), ) @@ -11221,10 +13808,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="locationId", default=None)), - ( - "address", - sgqlc.types.Arg(sgqlc.types.non_null(CompanyAddressInput), graphql_name="address", default=None), - ), + ("address", sgqlc.types.Arg(sgqlc.types.non_null(CompanyAddressInput), graphql_name="address", default=None)), ( "address_types", sgqlc.types.Arg( @@ -11241,10 +13825,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyLocationAssignRoles", args=sgqlc.types.ArgDict( ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), ( "roles_to_assign", sgqlc.types.Arg( @@ -11261,10 +13842,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyLocationAssignTaxExemptions", args=sgqlc.types.ArgDict( ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), ( "tax_exemptions", sgqlc.types.Arg( @@ -11282,10 +13860,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("company_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CompanyLocationInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(CompanyLocationInput), graphql_name="input", default=None)), ) ), ) @@ -11303,12 +13878,7 @@ class Mutation(sgqlc.types.Type): CompanyLocationDeletePayload, graphql_name="companyLocationDelete", args=sgqlc.types.ArgDict( - ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), - ) + (("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)),) ), ) company_location_revoke_roles = sgqlc.types.Field( @@ -11316,16 +13886,11 @@ class Mutation(sgqlc.types.Type): graphql_name="companyLocationRevokeRoles", args=sgqlc.types.ArgDict( ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), ( "roles_to_revoke", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="rolesToRevoke", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="rolesToRevoke", default=None ), ), ) @@ -11336,10 +13901,7 @@ class Mutation(sgqlc.types.Type): graphql_name="companyLocationRevokeTaxExemptions", args=sgqlc.types.ArgDict( ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), ( "tax_exemptions", sgqlc.types.Arg( @@ -11355,12 +13917,7 @@ class Mutation(sgqlc.types.Type): CompanyLocationRevokeTaxRegistrationPayload, graphql_name="companyLocationRevokeTaxRegistration", args=sgqlc.types.ArgDict( - ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), - ) + (("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)),) ), ) company_location_update = sgqlc.types.Field( @@ -11368,14 +13925,8 @@ class Mutation(sgqlc.types.Type): graphql_name="companyLocationUpdate", args=sgqlc.types.ArgDict( ( - ( - "company_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None), - ), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CompanyLocationUpdateInput), graphql_name="input", default=None), - ), + ("company_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="companyLocationId", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(CompanyLocationUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -11387,9 +13938,7 @@ class Mutation(sgqlc.types.Type): ( "company_location_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="companyLocationIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="companyLocationIds", default=None ), ), ) @@ -11445,21 +13994,45 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg( - sgqlc.types.non_null(CustomerEmailMarketingConsentUpdateInput), - graphql_name="input", - default=None, - ), + "input", + sgqlc.types.Arg(sgqlc.types.non_null(CustomerEmailMarketingConsentUpdateInput), graphql_name="input", default=None), + ), + ) + ), + ) + customer_generate_account_activation_url = sgqlc.types.Field( + CustomerGenerateAccountActivationUrlPayload, + graphql_name="customerGenerateAccountActivationUrl", + args=sgqlc.types.ArgDict((("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)),)), + ) + customer_merge = sgqlc.types.Field( + CustomerMergePayload, + graphql_name="customerMerge", + args=sgqlc.types.ArgDict( + ( + ("customer_one_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerOneId", default=None)), + ("customer_two_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerTwoId", default=None)), + ("override_fields", sgqlc.types.Arg(CustomerMergeOverrideFields, graphql_name="overrideFields", default=None)), + ) + ), + ) + customer_payment_method_create_from_duplication_data = sgqlc.types.Field( + CustomerPaymentMethodCreateFromDuplicationDataPayload, + graphql_name="customerPaymentMethodCreateFromDuplicationData", + args=sgqlc.types.ArgDict( + ( + ("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)), + ( + "billing_address", + sgqlc.types.Arg(sgqlc.types.non_null(MailingAddressInput), graphql_name="billingAddress", default=None), + ), + ( + "encrypted_duplication_data", + sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="encryptedDuplicationData", default=None), ), ) ), ) - customer_generate_account_activation_url = sgqlc.types.Field( - CustomerGenerateAccountActivationUrlPayload, - graphql_name="customerGenerateAccountActivationUrl", - args=sgqlc.types.ArgDict((("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)),)), - ) customer_payment_method_credit_card_create = sgqlc.types.Field( CustomerPaymentMethodCreditCardCreatePayload, graphql_name="customerPaymentMethodCreditCardCreate", @@ -11488,6 +14061,20 @@ class Mutation(sgqlc.types.Type): ) ), ) + customer_payment_method_get_duplication_data = sgqlc.types.Field( + CustomerPaymentMethodGetDuplicationDataPayload, + graphql_name="customerPaymentMethodGetDuplicationData", + args=sgqlc.types.ArgDict( + ( + ( + "customer_payment_method_id", + sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerPaymentMethodId", default=None), + ), + ("target_shop_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="targetShopId", default=None)), + ("target_customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="targetCustomerId", default=None)), + ) + ), + ) customer_payment_method_get_update_url = sgqlc.types.Field( CustomerPaymentMethodGetUpdateUrlPayload, graphql_name="customerPaymentMethodGetUpdateUrl", @@ -11507,10 +14094,7 @@ class Mutation(sgqlc.types.Type): ( ("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)), ("billing_address", sgqlc.types.Arg(MailingAddressInput, graphql_name="billingAddress", default=None)), - ( - "billing_agreement_id", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="billingAgreementId", default=None), - ), + ("billing_agreement_id", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="billingAgreementId", default=None)), ("inactive", sgqlc.types.Arg(Boolean, graphql_name="inactive", default=False)), ) ), @@ -11536,11 +14120,7 @@ class Mutation(sgqlc.types.Type): ("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)), ( "remote_reference", - sgqlc.types.Arg( - sgqlc.types.non_null(CustomerPaymentMethodRemoteInput), - graphql_name="remoteReference", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(CustomerPaymentMethodRemoteInput), graphql_name="remoteReference", default=None), ), ) ), @@ -11604,16 +14184,18 @@ class Mutation(sgqlc.types.Type): ) ), ) + customer_segment_members_query_create = sgqlc.types.Field( + CustomerSegmentMembersQueryCreatePayload, + graphql_name="customerSegmentMembersQueryCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(CustomerSegmentMembersQueryInput), graphql_name="input", default=None)),) + ), + ) customer_sms_marketing_consent_update = sgqlc.types.Field( CustomerSmsMarketingConsentUpdatePayload, graphql_name="customerSmsMarketingConsentUpdate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(CustomerSmsMarketingConsentUpdateInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(CustomerSmsMarketingConsentUpdateInput), graphql_name="input", default=None)),) ), ) customer_update = sgqlc.types.Field( @@ -11634,27 +14216,67 @@ class Mutation(sgqlc.types.Type): delegate_access_token_create = sgqlc.types.Field( DelegateAccessTokenCreatePayload, graphql_name="delegateAccessTokenCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(DelegateAccessTokenInput), graphql_name="input", default=None)),) + ), + ) + delegate_access_token_destroy = sgqlc.types.Field( + DelegateAccessTokenDestroyPayload, + graphql_name="delegateAccessTokenDestroy", + args=sgqlc.types.ArgDict( + (("access_token", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="accessToken", default=None)),) + ), + ) + delivery_customization_activation = sgqlc.types.Field( + DeliveryCustomizationActivationPayload, + graphql_name="deliveryCustomizationActivation", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(DelegateAccessTokenInput), graphql_name="input", default=None), + "ids", + sgqlc.types.Arg(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="ids", default=None), ), + ("enabled", sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="enabled", default=None)), ) ), ) - delivery_profile_create = sgqlc.types.Field( - "deliveryProfileCreatePayload", - graphql_name="deliveryProfileCreate", + delivery_customization_create = sgqlc.types.Field( + DeliveryCustomizationCreatePayload, + graphql_name="deliveryCustomizationCreate", + args=sgqlc.types.ArgDict( + ( + ( + "delivery_customization", + sgqlc.types.Arg(sgqlc.types.non_null(DeliveryCustomizationInput), graphql_name="deliveryCustomization", default=None), + ), + ) + ), + ) + delivery_customization_delete = sgqlc.types.Field( + DeliveryCustomizationDeletePayload, + graphql_name="deliveryCustomizationDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + delivery_customization_update = sgqlc.types.Field( + DeliveryCustomizationUpdatePayload, + graphql_name="deliveryCustomizationUpdate", args=sgqlc.types.ArgDict( ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( - "profile", - sgqlc.types.Arg(sgqlc.types.non_null(DeliveryProfileInput), graphql_name="profile", default=None), + "delivery_customization", + sgqlc.types.Arg(sgqlc.types.non_null(DeliveryCustomizationInput), graphql_name="deliveryCustomization", default=None), ), ) ), ) + delivery_profile_create = sgqlc.types.Field( + "deliveryProfileCreatePayload", + graphql_name="deliveryProfileCreate", + args=sgqlc.types.ArgDict( + (("profile", sgqlc.types.Arg(sgqlc.types.non_null(DeliveryProfileInput), graphql_name="profile", default=None)),) + ), + ) delivery_profile_remove = sgqlc.types.Field( "deliveryProfileRemovePayload", graphql_name="deliveryProfileRemove", @@ -11666,14 +14288,8 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "profile", - sgqlc.types.Arg(sgqlc.types.non_null(DeliveryProfileInput), graphql_name="profile", default=None), - ), - ( - "leave_legacy_mode_profiles", - sgqlc.types.Arg(Boolean, graphql_name="leaveLegacyModeProfiles", default=None), - ), + ("profile", sgqlc.types.Arg(sgqlc.types.non_null(DeliveryProfileInput), graphql_name="profile", default=None)), + ("leave_legacy_mode_profiles", sgqlc.types.Arg(Boolean, graphql_name="leaveLegacyModeProfiles", default=None)), ) ), ) @@ -11681,12 +14297,7 @@ class Mutation(sgqlc.types.Type): DeliverySettingUpdatePayload, graphql_name="deliverySettingUpdate", args=sgqlc.types.ArgDict( - ( - ( - "setting", - sgqlc.types.Arg(sgqlc.types.non_null(DeliverySettingInput), graphql_name="setting", default=None), - ), - ) + (("setting", sgqlc.types.Arg(sgqlc.types.non_null(DeliverySettingInput), graphql_name="setting", default=None)),) ), ) delivery_shipping_origin_assign = sgqlc.types.Field( @@ -11706,11 +14317,7 @@ class Mutation(sgqlc.types.Type): ( ( "automatic_app_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticAppInput), - graphql_name="automaticAppDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticAppInput), graphql_name="automaticAppDiscount", default=None), ), ) ), @@ -11723,11 +14330,7 @@ class Mutation(sgqlc.types.Type): ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( "automatic_app_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticAppInput), - graphql_name="automaticAppDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticAppInput), graphql_name="automaticAppDiscount", default=None), ), ) ), @@ -11739,11 +14342,7 @@ class Mutation(sgqlc.types.Type): ( ( "automatic_basic_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticBasicInput), - graphql_name="automaticBasicDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticBasicInput), graphql_name="automaticBasicDiscount", default=None), ), ) ), @@ -11756,11 +14355,7 @@ class Mutation(sgqlc.types.Type): ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( "automatic_basic_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticBasicInput), - graphql_name="automaticBasicDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticBasicInput), graphql_name="automaticBasicDiscount", default=None), ), ) ), @@ -11772,10 +14367,7 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -11786,11 +14378,7 @@ class Mutation(sgqlc.types.Type): ( ( "automatic_bxgy_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticBxgyInput), - graphql_name="automaticBxgyDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticBxgyInput), graphql_name="automaticBxgyDiscount", default=None), ), ) ), @@ -11803,11 +14391,7 @@ class Mutation(sgqlc.types.Type): ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( "automatic_bxgy_discount", - sgqlc.types.Arg( - sgqlc.types.non_null(DiscountAutomaticBxgyInput), - graphql_name="automaticBxgyDiscount", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(DiscountAutomaticBxgyInput), graphql_name="automaticBxgyDiscount", default=None), ), ) ), @@ -11884,10 +14468,7 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -11898,10 +14479,7 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -11912,10 +14490,7 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -11962,9 +14537,7 @@ class Mutation(sgqlc.types.Type): ( "free_shipping_code_discount", sgqlc.types.Arg( - sgqlc.types.non_null(DiscountCodeFreeShippingInput), - graphql_name="freeShippingCodeDiscount", - default=None, + sgqlc.types.non_null(DiscountCodeFreeShippingInput), graphql_name="freeShippingCodeDiscount", default=None ), ), ) @@ -11979,9 +14552,7 @@ class Mutation(sgqlc.types.Type): ( "free_shipping_code_discount", sgqlc.types.Arg( - sgqlc.types.non_null(DiscountCodeFreeShippingInput), - graphql_name="freeShippingCodeDiscount", - default=None, + sgqlc.types.non_null(DiscountCodeFreeShippingInput), graphql_name="freeShippingCodeDiscount", default=None ), ), ) @@ -11995,10 +14566,7 @@ class Mutation(sgqlc.types.Type): ("discount_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="discountId", default=None)), ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -12027,11 +14595,7 @@ class Mutation(sgqlc.types.Type): ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( "input", - sgqlc.types.Arg( - sgqlc.types.non_null(ShopifyPaymentsDisputeEvidenceUpdateInput), - graphql_name="input", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(ShopifyPaymentsDisputeEvidenceUpdateInput), graphql_name="input", default=None), ), ) ), @@ -12043,16 +14607,11 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ( "tags", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="tags", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags", default=None ), ), ) @@ -12065,10 +14624,7 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ) ), ) @@ -12079,16 +14635,11 @@ class Mutation(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(String, graphql_name="search", default=None)), ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ( - "ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None), - ), + ("ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="ids", default=None)), ( "tags", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="tags", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags", default=None ), ), ) @@ -12130,12 +14681,7 @@ class Mutation(sgqlc.types.Type): DraftOrderDeletePayload, graphql_name="draftOrderDelete", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(DraftOrderDeleteInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(DraftOrderDeleteInput), graphql_name="input", default=None)),) ), ) draft_order_duplicate = sgqlc.types.Field( @@ -12173,21 +14719,21 @@ class Mutation(sgqlc.types.Type): ) ), ) + event_bridge_server_pixel_update = sgqlc.types.Field( + EventBridgeServerPixelUpdatePayload, + graphql_name="eventBridgeServerPixelUpdate", + args=sgqlc.types.ArgDict((("arn", sgqlc.types.Arg(sgqlc.types.non_null(ARN), graphql_name="arn", default=None)),)), + ) event_bridge_webhook_subscription_create = sgqlc.types.Field( EventBridgeWebhookSubscriptionCreatePayload, graphql_name="eventBridgeWebhookSubscriptionCreate", args=sgqlc.types.ArgDict( ( - ( - "topic", - sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None), - ), + ("topic", sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None)), ( "webhook_subscription", sgqlc.types.Arg( - sgqlc.types.non_null(EventBridgeWebhookSubscriptionInput), - graphql_name="webhookSubscription", - default=None, + sgqlc.types.non_null(EventBridgeWebhookSubscriptionInput), graphql_name="webhookSubscription", default=None ), ), ) @@ -12202,9 +14748,21 @@ class Mutation(sgqlc.types.Type): ( "webhook_subscription", sgqlc.types.Arg( - sgqlc.types.non_null(EventBridgeWebhookSubscriptionInput), - graphql_name="webhookSubscription", - default=None, + sgqlc.types.non_null(EventBridgeWebhookSubscriptionInput), graphql_name="webhookSubscription", default=None + ), + ), + ) + ), + ) + file_acknowledge_update_failed = sgqlc.types.Field( + FileAcknowledgeUpdateFailedPayload, + graphql_name="fileAcknowledgeUpdateFailed", + args=sgqlc.types.ArgDict( + ( + ( + "file_ids", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="fileIds", default=None ), ), ) @@ -12218,9 +14776,7 @@ class Mutation(sgqlc.types.Type): ( "files", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FileCreateInput))), - graphql_name="files", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FileCreateInput))), graphql_name="files", default=None ), ), ) @@ -12234,9 +14790,7 @@ class Mutation(sgqlc.types.Type): ( "file_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="fileIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="fileIds", default=None ), ), ) @@ -12250,9 +14804,7 @@ class Mutation(sgqlc.types.Type): ( "files", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FileUpdateInput))), - graphql_name="files", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FileUpdateInput))), graphql_name="files", default=None ), ), ) @@ -12271,13 +14823,22 @@ class Mutation(sgqlc.types.Type): fulfillment_create_v2 = sgqlc.types.Field( FulfillmentCreateV2Payload, graphql_name="fulfillmentCreateV2", + args=sgqlc.types.ArgDict( + ( + ("fulfillment", sgqlc.types.Arg(sgqlc.types.non_null(FulfillmentV2Input), graphql_name="fulfillment", default=None)), + ("message", sgqlc.types.Arg(String, graphql_name="message", default=None)), + ) + ), + ) + fulfillment_event_create = sgqlc.types.Field( + FulfillmentEventCreatePayload, + graphql_name="fulfillmentEventCreate", args=sgqlc.types.ArgDict( ( ( - "fulfillment", - sgqlc.types.Arg(sgqlc.types.non_null(FulfillmentV2Input), graphql_name="fulfillment", default=None), + "fulfillment_event", + sgqlc.types.Arg(sgqlc.types.non_null(FulfillmentEventInput), graphql_name="fulfillmentEvent", default=None), ), - ("message", sgqlc.types.Arg(String, graphql_name="message", default=None)), ) ), ) @@ -12329,15 +14890,50 @@ class Mutation(sgqlc.types.Type): ) ), ) + fulfillment_order_line_items_prepared_for_pickup = sgqlc.types.Field( + FulfillmentOrderLineItemsPreparedForPickupPayload, + graphql_name="fulfillmentOrderLineItemsPreparedForPickup", + args=sgqlc.types.ArgDict( + ( + ( + "input", + sgqlc.types.Arg( + sgqlc.types.non_null(FulfillmentOrderLineItemsPreparedForPickupInput), graphql_name="input", default=None + ), + ), + ) + ), + ) + fulfillment_order_merge = sgqlc.types.Field( + FulfillmentOrderMergePayload, + graphql_name="fulfillmentOrderMerge", + args=sgqlc.types.ArgDict( + ( + ( + "fulfillment_order_merge_inputs", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderMergeInput))), + graphql_name="fulfillmentOrderMergeInputs", + default=None, + ), + ), + ) + ), + ) fulfillment_order_move = sgqlc.types.Field( FulfillmentOrderMovePayload, graphql_name="fulfillmentOrderMove", args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("new_location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="newLocationId", default=None)), ( - "new_location_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="newLocationId", default=None), + "fulfillment_order_line_items", + sgqlc.types.Arg( + sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemInput)), + graphql_name="fulfillmentOrderLineItems", + default=None, + ), ), ) ), @@ -12368,9 +14964,7 @@ class Mutation(sgqlc.types.Type): ( "line_items", sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(IncomingRequestLineItemInput)), - graphql_name="lineItems", - default=None, + sgqlc.types.list_of(sgqlc.types.non_null(IncomingRequestLineItemInput)), graphql_name="lineItems", default=None ), ), ) @@ -12379,7 +14973,12 @@ class Mutation(sgqlc.types.Type): fulfillment_order_release_hold = sgqlc.types.Field( FulfillmentOrderReleaseHoldPayload, graphql_name="fulfillmentOrderReleaseHold", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("external_id", sgqlc.types.Arg(String, graphql_name="externalId", default=None)), + ) + ), ) fulfillment_order_reschedule = sgqlc.types.Field( FulfillmentOrderReschedulePayload, @@ -12391,6 +14990,22 @@ class Mutation(sgqlc.types.Type): ) ), ) + fulfillment_order_split = sgqlc.types.Field( + FulfillmentOrderSplitPayload, + graphql_name="fulfillmentOrderSplit", + args=sgqlc.types.ArgDict( + ( + ( + "fulfillment_order_splits", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderSplitInput))), + graphql_name="fulfillmentOrderSplits", + default=None, + ), + ), + ) + ), + ) fulfillment_order_submit_cancellation_request = sgqlc.types.Field( FulfillmentOrderSubmitCancellationRequestPayload, graphql_name="fulfillmentOrderSubmitCancellationRequest", @@ -12421,6 +15036,19 @@ class Mutation(sgqlc.types.Type): ) ), ) + fulfillment_orders_release_holds = sgqlc.types.Field( + FulfillmentOrdersReleaseHoldsPayload, + graphql_name="fulfillmentOrdersReleaseHolds", + args=sgqlc.types.ArgDict( + ( + ( + "ids", + sgqlc.types.Arg(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="ids", default=None), + ), + ("external_id", sgqlc.types.Arg(String, graphql_name="externalId", default=None)), + ) + ), + ) fulfillment_orders_set_fulfillment_deadline = sgqlc.types.Field( FulfillmentOrdersSetFulfillmentDeadlinePayload, graphql_name="fulfillmentOrdersSetFulfillmentDeadline", @@ -12434,10 +15062,7 @@ class Mutation(sgqlc.types.Type): default=None, ), ), - ( - "fulfillment_deadline", - sgqlc.types.Arg(sgqlc.types.non_null(DateTime), graphql_name="fulfillmentDeadline", default=None), - ), + ("fulfillment_deadline", sgqlc.types.Arg(sgqlc.types.non_null(DateTime), graphql_name="fulfillmentDeadline", default=None)), ) ), ) @@ -12447,11 +15072,11 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("name", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="name", default=None)), - ("callback_url", sgqlc.types.Arg(URL, graphql_name="callbackUrl", default=None)), + ("callback_url", sgqlc.types.Arg(sgqlc.types.non_null(URL), graphql_name="callbackUrl", default=None)), ("tracking_support", sgqlc.types.Arg(Boolean, graphql_name="trackingSupport", default=False)), ( "fulfillment_orders_opt_in", - sgqlc.types.Arg(Boolean, graphql_name="fulfillmentOrdersOptIn", default=False), + sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="fulfillmentOrdersOptIn", default=None), ), ("permits_sku_sharing", sgqlc.types.Arg(Boolean, graphql_name="permitsSkuSharing", default=False)), ("inventory_management", sgqlc.types.Arg(Boolean, graphql_name="inventoryManagement", default=False)), @@ -12477,10 +15102,7 @@ class Mutation(sgqlc.types.Type): ("name", sgqlc.types.Arg(String, graphql_name="name", default=None)), ("callback_url", sgqlc.types.Arg(URL, graphql_name="callbackUrl", default=None)), ("tracking_support", sgqlc.types.Arg(Boolean, graphql_name="trackingSupport", default=None)), - ( - "fulfillment_orders_opt_in", - sgqlc.types.Arg(Boolean, graphql_name="fulfillmentOrdersOptIn", default=None), - ), + ("fulfillment_orders_opt_in", sgqlc.types.Arg(Boolean, graphql_name="fulfillmentOrdersOptIn", default=None)), ("permits_sku_sharing", sgqlc.types.Arg(Boolean, graphql_name="permitsSkuSharing", default=None)), ) ), @@ -12490,10 +15112,7 @@ class Mutation(sgqlc.types.Type): graphql_name="fulfillmentTrackingInfoUpdateV2", args=sgqlc.types.ArgDict( ( - ( - "fulfillment_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="fulfillmentId", default=None), - ), + ("fulfillment_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="fulfillmentId", default=None)), ( "tracking_info_input", sgqlc.types.Arg(sgqlc.types.non_null(FulfillmentTrackingInput), graphql_name="trackingInfoInput", default=None), @@ -12520,10 +15139,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(GiftCardUpdateInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(GiftCardUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -12532,42 +15148,18 @@ class Mutation(sgqlc.types.Type): graphql_name="inventoryActivate", args=sgqlc.types.ArgDict( ( - ( - "inventory_item_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None), - ), + ("inventory_item_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None)), ("location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="locationId", default=None)), ("available", sgqlc.types.Arg(Int, graphql_name="available", default=None)), + ("on_hand", sgqlc.types.Arg(Int, graphql_name="onHand", default=None)), ) ), ) - inventory_adjust_quantity = sgqlc.types.Field( - InventoryAdjustQuantityPayload, - graphql_name="inventoryAdjustQuantity", - args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(InventoryAdjustQuantityInput), graphql_name="input", default=None), - ), - ) - ), - ) - inventory_bulk_adjust_quantity_at_location = sgqlc.types.Field( - InventoryBulkAdjustQuantityAtLocationPayload, - graphql_name="inventoryBulkAdjustQuantityAtLocation", + inventory_adjust_quantities = sgqlc.types.Field( + InventoryAdjustQuantitiesPayload, + graphql_name="inventoryAdjustQuantities", args=sgqlc.types.ArgDict( - ( - ( - "inventory_item_adjustments", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(InventoryAdjustItemInput))), - graphql_name="inventoryItemAdjustments", - default=None, - ), - ), - ("location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="locationId", default=None)), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(InventoryAdjustQuantitiesInput), graphql_name="input", default=None)),) ), ) inventory_bulk_toggle_activation = sgqlc.types.Field( @@ -12575,10 +15167,7 @@ class Mutation(sgqlc.types.Type): graphql_name="inventoryBulkToggleActivation", args=sgqlc.types.ArgDict( ( - ( - "inventory_item_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None), - ), + ("inventory_item_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None)), ( "inventory_item_updates", sgqlc.types.Arg( @@ -12594,12 +15183,7 @@ class Mutation(sgqlc.types.Type): InventoryDeactivatePayload, graphql_name="inventoryDeactivate", args=sgqlc.types.ArgDict( - ( - ( - "inventory_level_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryLevelId", default=None), - ), - ) + (("inventory_level_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryLevelId", default=None)),) ), ) inventory_item_update = sgqlc.types.Field( @@ -12608,13 +15192,24 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(InventoryItemUpdateInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(InventoryItemUpdateInput), graphql_name="input", default=None)), ) ), ) + inventory_move_quantities = sgqlc.types.Field( + InventoryMoveQuantitiesPayload, + graphql_name="inventoryMoveQuantities", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(InventoryMoveQuantitiesInput), graphql_name="input", default=None)),) + ), + ) + inventory_set_on_hand_quantities = sgqlc.types.Field( + InventorySetOnHandQuantitiesPayload, + graphql_name="inventorySetOnHandQuantities", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(InventorySetOnHandQuantitiesInput), graphql_name="input", default=None)),) + ), + ) location_activate = sgqlc.types.Field( LocationActivatePayload, graphql_name="locationActivate", @@ -12650,6 +15245,25 @@ class Mutation(sgqlc.types.Type): ) ), ) + location_local_pickup_disable = sgqlc.types.Field( + LocationLocalPickupDisablePayload, + graphql_name="locationLocalPickupDisable", + args=sgqlc.types.ArgDict((("location_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="locationId", default=None)),)), + ) + location_local_pickup_enable = sgqlc.types.Field( + LocationLocalPickupEnablePayload, + graphql_name="locationLocalPickupEnable", + args=sgqlc.types.ArgDict( + ( + ( + "local_pickup_settings", + sgqlc.types.Arg( + sgqlc.types.non_null(DeliveryLocationLocalPickupEnableInput), graphql_name="localPickupSettings", default=None + ), + ), + ) + ), + ) market_create = sgqlc.types.Field( MarketCreatePayload, graphql_name="marketCreate", @@ -12663,10 +15277,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("market_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="marketId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MarketCurrencySettingsUpdateInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(MarketCurrencySettingsUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -12709,9 +15320,7 @@ class Mutation(sgqlc.types.Type): ( "market_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="marketIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="marketIds", default=None ), ), ) @@ -12784,36 +15393,21 @@ class Mutation(sgqlc.types.Type): MarketingActivityCreatePayload, graphql_name="marketingActivityCreate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityCreateInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityCreateInput), graphql_name="input", default=None)),) ), ) marketing_activity_create_external = sgqlc.types.Field( MarketingActivityCreateExternalPayload, graphql_name="marketingActivityCreateExternal", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityCreateExternalInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityCreateExternalInput), graphql_name="input", default=None)),) ), ) marketing_activity_update = sgqlc.types.Field( MarketingActivityUpdatePayload, graphql_name="marketingActivityUpdate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityUpdateInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityUpdateInput), graphql_name="input", default=None)),) ), ) marketing_activity_update_external = sgqlc.types.Field( @@ -12821,10 +15415,7 @@ class Mutation(sgqlc.types.Type): graphql_name="marketingActivityUpdateExternal", args=sgqlc.types.ArgDict( ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityUpdateExternalInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(MarketingActivityUpdateExternalInput), graphql_name="input", default=None)), ("marketing_activity_id", sgqlc.types.Arg(ID, graphql_name="marketingActivityId", default=None)), ("remote_id", sgqlc.types.Arg(String, graphql_name="remoteId", default=None)), ("utm", sgqlc.types.Arg(UTMInput, graphql_name="utm", default=None)), @@ -12836,10 +15427,7 @@ class Mutation(sgqlc.types.Type): graphql_name="marketingEngagementCreate", args=sgqlc.types.ArgDict( ( - ( - "marketing_activity_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="marketingActivityId", default=None), - ), + ("marketing_activity_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="marketingActivityId", default=None)), ( "marketing_engagement", sgqlc.types.Arg(sgqlc.types.non_null(MarketingEngagementInput), graphql_name="marketingEngagement", default=None), @@ -12851,12 +15439,7 @@ class Mutation(sgqlc.types.Type): MetafieldDefinitionCreatePayload, graphql_name="metafieldDefinitionCreate", args=sgqlc.types.ArgDict( - ( - ( - "definition", - sgqlc.types.Arg(sgqlc.types.non_null(MetafieldDefinitionInput), graphql_name="definition", default=None), - ), - ) + (("definition", sgqlc.types.Arg(sgqlc.types.non_null(MetafieldDefinitionInput), graphql_name="definition", default=None)),) ), ) metafield_definition_delete = sgqlc.types.Field( @@ -12865,10 +15448,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "delete_all_associated_metafields", - sgqlc.types.Arg(Boolean, graphql_name="deleteAllAssociatedMetafields", default=False), - ), + ("delete_all_associated_metafields", sgqlc.types.Arg(Boolean, graphql_name="deleteAllAssociatedMetafields", default=False)), ) ), ) @@ -12901,48 +15481,95 @@ class Mutation(sgqlc.types.Type): metafield_delete = sgqlc.types.Field( MetafieldDeletePayload, graphql_name="metafieldDelete", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(MetafieldDeleteInput), graphql_name="input", default=None)),) + ), + ) + metafields_set = sgqlc.types.Field( + MetafieldsSetPayload, + graphql_name="metafieldsSet", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MetafieldDeleteInput), graphql_name="input", default=None), + "metafields", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldsSetInput))), + graphql_name="metafields", + default=None, + ), ), ) ), ) - metafield_storefront_visibility_create = sgqlc.types.Field( - MetafieldStorefrontVisibilityCreatePayload, - graphql_name="metafieldStorefrontVisibilityCreate", + metaobject_bulk_delete = sgqlc.types.Field( + MetaobjectBulkDeletePayload, + graphql_name="metaobjectBulkDelete", + args=sgqlc.types.ArgDict( + (("where", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectBulkDeleteWhereCondition), graphql_name="where", default=None)),) + ), + ) + metaobject_create = sgqlc.types.Field( + MetaobjectCreatePayload, + graphql_name="metaobjectCreate", + args=sgqlc.types.ArgDict( + (("metaobject", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectCreateInput), graphql_name="metaobject", default=None)),) + ), + ) + metaobject_definition_create = sgqlc.types.Field( + MetaobjectDefinitionCreatePayload, + graphql_name="metaobjectDefinitionCreate", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(MetafieldStorefrontVisibilityInput), graphql_name="input", default=None), + "definition", + sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectDefinitionCreateInput), graphql_name="definition", default=None), ), ) ), ) - metafield_storefront_visibility_delete = sgqlc.types.Field( - MetafieldStorefrontVisibilityDeletePayload, - graphql_name="metafieldStorefrontVisibilityDelete", + metaobject_definition_delete = sgqlc.types.Field( + MetaobjectDefinitionDeletePayload, + graphql_name="metaobjectDefinitionDelete", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) - metafields_set = sgqlc.types.Field( - MetafieldsSetPayload, - graphql_name="metafieldsSet", + metaobject_definition_update = sgqlc.types.Field( + MetaobjectDefinitionUpdatePayload, + graphql_name="metaobjectDefinitionUpdate", args=sgqlc.types.ArgDict( ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ( - "metafields", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldsSetInput))), - graphql_name="metafields", - default=None, - ), + "definition", + sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectDefinitionUpdateInput), graphql_name="definition", default=None), ), ) ), ) + metaobject_delete = sgqlc.types.Field( + MetaobjectDeletePayload, + graphql_name="metaobjectDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + metaobject_update = sgqlc.types.Field( + MetaobjectUpdatePayload, + graphql_name="metaobjectUpdate", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("metaobject", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectUpdateInput), graphql_name="metaobject", default=None)), + ) + ), + ) + metaobject_upsert = sgqlc.types.Field( + MetaobjectUpsertPayload, + graphql_name="metaobjectUpsert", + args=sgqlc.types.ArgDict( + ( + ("handle", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectHandleInput), graphql_name="handle", default=None)), + ("metaobject", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectUpsertInput), graphql_name="metaobject", default=None)), + ) + ), + ) order_capture = sgqlc.types.Field( "OrderCapturePayload", graphql_name="orderCapture", @@ -12962,10 +15589,7 @@ class Mutation(sgqlc.types.Type): ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ("payment_schedule_id", sgqlc.types.Arg(ID, graphql_name="paymentScheduleId", default=None)), - ( - "idempotency_key", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="idempotencyKey", default=None), - ), + ("idempotency_key", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="idempotencyKey", default=None)), ("mandate_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="mandateId", default=None)), ("auto_capture", sgqlc.types.Arg(Boolean, graphql_name="autoCapture", default=True)), ) @@ -12993,10 +15617,7 @@ class Mutation(sgqlc.types.Type): ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), ("line_item_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="lineItemId", default=None)), - ( - "discount", - sgqlc.types.Arg(sgqlc.types.non_null(OrderEditAppliedDiscountInput), graphql_name="discount", default=None), - ), + ("discount", sgqlc.types.Arg(sgqlc.types.non_null(OrderEditAppliedDiscountInput), graphql_name="discount", default=None)), ) ), ) @@ -13035,10 +15656,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "discount_application_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="discountApplicationId", default=None), - ), + ("discount_application_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="discountApplicationId", default=None)), ) ), ) @@ -13068,12 +15686,7 @@ class Mutation(sgqlc.types.Type): "OrderMarkAsPaidPayload", graphql_name="orderMarkAsPaid", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(OrderMarkAsPaidInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(OrderMarkAsPaidInput), graphql_name="input", default=None)),) ), ) order_open = sgqlc.types.Field( @@ -13086,6 +15699,56 @@ class Mutation(sgqlc.types.Type): graphql_name="orderUpdate", args=sgqlc.types.ArgDict((("input", sgqlc.types.Arg(sgqlc.types.non_null(OrderInput), graphql_name="input", default=None)),)), ) + payment_customization_activation = sgqlc.types.Field( + "PaymentCustomizationActivationPayload", + graphql_name="paymentCustomizationActivation", + args=sgqlc.types.ArgDict( + ( + ( + "ids", + sgqlc.types.Arg(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="ids", default=None), + ), + ("enabled", sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="enabled", default=None)), + ) + ), + ) + payment_customization_create = sgqlc.types.Field( + "PaymentCustomizationCreatePayload", + graphql_name="paymentCustomizationCreate", + args=sgqlc.types.ArgDict( + ( + ( + "payment_customization", + sgqlc.types.Arg(sgqlc.types.non_null(PaymentCustomizationInput), graphql_name="paymentCustomization", default=None), + ), + ) + ), + ) + payment_customization_delete = sgqlc.types.Field( + "PaymentCustomizationDeletePayload", + graphql_name="paymentCustomizationDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + payment_customization_update = sgqlc.types.Field( + "PaymentCustomizationUpdatePayload", + graphql_name="paymentCustomizationUpdate", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ( + "payment_customization", + sgqlc.types.Arg(sgqlc.types.non_null(PaymentCustomizationInput), graphql_name="paymentCustomization", default=None), + ), + ) + ), + ) + payment_reminder_send = sgqlc.types.Field( + "PaymentReminderSendPayload", + graphql_name="paymentReminderSend", + args=sgqlc.types.ArgDict( + (("payment_schedule_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="paymentScheduleId", default=None)),) + ), + ) payment_terms_create = sgqlc.types.Field( "PaymentTermsCreatePayload", graphql_name="paymentTermsCreate", @@ -13094,11 +15757,7 @@ class Mutation(sgqlc.types.Type): ("reference_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="referenceId", default=None)), ( "payment_terms_attributes", - sgqlc.types.Arg( - sgqlc.types.non_null(PaymentTermsCreateInput), - graphql_name="paymentTermsAttributes", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(PaymentTermsCreateInput), graphql_name="paymentTermsAttributes", default=None), ), ) ), @@ -13107,36 +15766,21 @@ class Mutation(sgqlc.types.Type): "PaymentTermsDeletePayload", graphql_name="paymentTermsDelete", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PaymentTermsDeleteInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(PaymentTermsDeleteInput), graphql_name="input", default=None)),) ), ) payment_terms_update = sgqlc.types.Field( "PaymentTermsUpdatePayload", graphql_name="paymentTermsUpdate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PaymentTermsUpdateInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(PaymentTermsUpdateInput), graphql_name="input", default=None)),) ), ) price_list_create = sgqlc.types.Field( "PriceListCreatePayload", graphql_name="priceListCreate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PriceListCreateInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(PriceListCreateInput), graphql_name="input", default=None)),) ), ) price_list_delete = sgqlc.types.Field( @@ -13161,137 +15805,70 @@ class Mutation(sgqlc.types.Type): ) ), ) - price_list_fixed_prices_delete = sgqlc.types.Field( - "PriceListFixedPricesDeletePayload", - graphql_name="priceListFixedPricesDelete", + price_list_fixed_prices_by_product_update = sgqlc.types.Field( + "PriceListFixedPricesByProductUpdatePayload", + graphql_name="priceListFixedPricesByProductUpdate", args=sgqlc.types.ArgDict( ( - ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), ( - "variant_ids", + "prices_to_add", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="variantIds", - default=None, + sgqlc.types.list_of(sgqlc.types.non_null(PriceListProductPriceInput)), graphql_name="pricesToAdd", default=None ), ), - ) - ), - ) - price_list_update = sgqlc.types.Field( - "PriceListUpdatePayload", - graphql_name="priceListUpdate", - args=sgqlc.types.ArgDict( - ( - ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PriceListUpdateInput), graphql_name="input", default=None), - ), - ) - ), - ) - price_rule_activate = sgqlc.types.Field( - "PriceRuleActivatePayload", - graphql_name="priceRuleActivate", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) - price_rule_create = sgqlc.types.Field( - "PriceRuleCreatePayload", - graphql_name="priceRuleCreate", - args=sgqlc.types.ArgDict( - ( - ( - "price_rule", - sgqlc.types.Arg(sgqlc.types.non_null(PriceRuleInput), graphql_name="priceRule", default=None), - ), ( - "price_rule_discount_code", - sgqlc.types.Arg(PriceRuleDiscountCodeInput, graphql_name="priceRuleDiscountCode", default=None), + "prices_to_delete_by_product_ids", + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="pricesToDeleteByProductIds", default=None), ), + ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), ) ), ) - price_rule_deactivate = sgqlc.types.Field( - "PriceRuleDeactivatePayload", - graphql_name="priceRuleDeactivate", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) - price_rule_delete = sgqlc.types.Field( - "PriceRuleDeletePayload", - graphql_name="priceRuleDelete", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) - price_rule_discount_code_create = sgqlc.types.Field( - "PriceRuleDiscountCodeCreatePayload", - graphql_name="priceRuleDiscountCodeCreate", - args=sgqlc.types.ArgDict( - ( - ("price_rule_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceRuleId", default=None)), - ("code", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="code", default=None)), - ) - ), - ) - price_rule_discount_code_update = sgqlc.types.Field( - "PriceRuleDiscountCodeUpdatePayload", - graphql_name="priceRuleDiscountCodeUpdate", - args=sgqlc.types.ArgDict( - ( - ("price_rule_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceRuleId", default=None)), - ("code", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="code", default=None)), - ) - ), - ) - price_rule_update = sgqlc.types.Field( - "PriceRuleUpdatePayload", - graphql_name="priceRuleUpdate", + price_list_fixed_prices_delete = sgqlc.types.Field( + "PriceListFixedPricesDeletePayload", + graphql_name="priceListFixedPricesDelete", args=sgqlc.types.ArgDict( ( - ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "price_rule", - sgqlc.types.Arg(sgqlc.types.non_null(PriceRuleInput), graphql_name="priceRule", default=None), - ), + ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), ( - "price_rule_discount_code", - sgqlc.types.Arg(PriceRuleDiscountCodeInput, graphql_name="priceRuleDiscountCode", default=None), + "variant_ids", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="variantIds", default=None + ), ), ) ), ) - private_metafield_delete = sgqlc.types.Field( - "PrivateMetafieldDeletePayload", - graphql_name="privateMetafieldDelete", + price_list_fixed_prices_update = sgqlc.types.Field( + "PriceListFixedPricesUpdatePayload", + graphql_name="priceListFixedPricesUpdate", args=sgqlc.types.ArgDict( ( + ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PrivateMetafieldDeleteInput), graphql_name="input", default=None), + "prices_to_add", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(PriceListPriceInput))), + graphql_name="pricesToAdd", + default=None, + ), ), - ) - ), - ) - private_metafield_upsert = sgqlc.types.Field( - "PrivateMetafieldUpsertPayload", - graphql_name="privateMetafieldUpsert", - args=sgqlc.types.ArgDict( - ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(PrivateMetafieldInput), graphql_name="input", default=None), + "variant_ids_to_delete", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="variantIdsToDelete", default=None + ), ), ) ), ) - product_append_images = sgqlc.types.Field( - "ProductAppendImagesPayload", - graphql_name="productAppendImages", + price_list_update = sgqlc.types.Field( + "PriceListUpdatePayload", + graphql_name="priceListUpdate", args=sgqlc.types.ArgDict( ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(ProductAppendImagesInput), graphql_name="input", default=None), - ), + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(PriceListUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -13311,10 +15888,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("input", sgqlc.types.Arg(sgqlc.types.non_null(ProductInput), graphql_name="input", default=None)), - ( - "media", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CreateMediaInput)), graphql_name="media", default=None), - ), + ("media", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CreateMediaInput)), graphql_name="media", default=None)), ) ), ) @@ -13342,22 +15916,10 @@ class Mutation(sgqlc.types.Type): (("input", sgqlc.types.Arg(sgqlc.types.non_null(ProductDeleteInput), graphql_name="input", default=None)),) ), ) - product_delete_images = sgqlc.types.Field( - "ProductDeleteImagesPayload", - graphql_name="productDeleteImages", - args=sgqlc.types.ArgDict( - ( - ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "image_ids", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="imageIds", - default=None, - ), - ), - ) - ), + product_delete_async = sgqlc.types.Field( + "ProductDeleteAsyncPayload", + graphql_name="productDeleteAsync", + args=sgqlc.types.ArgDict((("product_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productId", default=None)),)), ) product_delete_media = sgqlc.types.Field( "ProductDeleteMediaPayload", @@ -13368,9 +15930,7 @@ class Mutation(sgqlc.types.Type): ( "media_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="mediaIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="mediaIds", default=None ), ), ) @@ -13388,13 +15948,31 @@ class Mutation(sgqlc.types.Type): ) ), ) - product_image_update = sgqlc.types.Field( - "ProductImageUpdatePayload", - graphql_name="productImageUpdate", + product_duplicate_async_v2 = sgqlc.types.Field( + "ProductDuplicateAsyncV2Payload", + graphql_name="productDuplicateAsyncV2", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(ProductDuplicateAsyncInput), graphql_name="input", default=None)),) + ), + ) + product_feed_create = sgqlc.types.Field( + "ProductFeedCreatePayload", + graphql_name="productFeedCreate", + args=sgqlc.types.ArgDict((("input", sgqlc.types.Arg(ProductFeedInput, graphql_name="input", default=None)),)), + ) + product_feed_delete = sgqlc.types.Field( + "ProductFeedDeletePayload", + graphql_name="productFeedDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + product_full_sync = sgqlc.types.Field( + "ProductFullSyncPayload", + graphql_name="productFullSync", args=sgqlc.types.ArgDict( ( - ("product_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productId", default=None)), - ("image", sgqlc.types.Arg(sgqlc.types.non_null(ImageInput), graphql_name="image", default=None)), + ("before_updated_at", sgqlc.types.Arg(DateTime, graphql_name="beforeUpdatedAt", default=None)), + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("updated_at_since", sgqlc.types.Arg(DateTime, graphql_name="updatedAtSince", default=None)), ) ), ) @@ -13432,23 +16010,6 @@ class Mutation(sgqlc.types.Type): ) ), ) - product_reorder_images = sgqlc.types.Field( - "ProductReorderImagesPayload", - graphql_name="productReorderImages", - args=sgqlc.types.ArgDict( - ( - ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "moves", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MoveInput))), - graphql_name="moves", - default=None, - ), - ), - ) - ), - ) product_reorder_media = sgqlc.types.Field( "ProductReorderMediaPayload", graphql_name="productReorderMedia", @@ -13458,9 +16019,7 @@ class Mutation(sgqlc.types.Type): ( "moves", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MoveInput))), - graphql_name="moves", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MoveInput))), graphql_name="moves", default=None ), ), ) @@ -13469,7 +16028,12 @@ class Mutation(sgqlc.types.Type): product_update = sgqlc.types.Field( "ProductUpdatePayload", graphql_name="productUpdate", - args=sgqlc.types.ArgDict((("input", sgqlc.types.Arg(sgqlc.types.non_null(ProductInput), graphql_name="input", default=None)),)), + args=sgqlc.types.ArgDict( + ( + ("input", sgqlc.types.Arg(sgqlc.types.non_null(ProductInput), graphql_name="input", default=None)), + ("media", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CreateMediaInput)), graphql_name="media", default=None)), + ) + ), ) product_update_media = sgqlc.types.Field( "ProductUpdateMediaPayload", @@ -13568,6 +16132,22 @@ class Mutation(sgqlc.types.Type): ) ), ) + product_variant_relationship_bulk_update = sgqlc.types.Field( + "ProductVariantRelationshipBulkUpdatePayload", + graphql_name="productVariantRelationshipBulkUpdate", + args=sgqlc.types.ArgDict( + ( + ( + "input", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductVariantRelationshipUpdateInput))), + graphql_name="input", + default=None, + ), + ), + ) + ), + ) product_variant_update = sgqlc.types.Field( "ProductVariantUpdatePayload", graphql_name="productVariantUpdate", @@ -13589,6 +16169,7 @@ class Mutation(sgqlc.types.Type): ), ), ("product_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productId", default=None)), + ("media", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CreateMediaInput)), graphql_name="media", default=None)), ) ), ) @@ -13600,9 +16181,7 @@ class Mutation(sgqlc.types.Type): ( "variants_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="variantsIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="variantsIds", default=None ), ), ("product_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productId", default=None)), @@ -13640,6 +16219,18 @@ class Mutation(sgqlc.types.Type): ), ), ("product_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productId", default=None)), + ("media", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CreateMediaInput)), graphql_name="media", default=None)), + ("allow_partial_updates", sgqlc.types.Arg(Boolean, graphql_name="allowPartialUpdates", default=False)), + ) + ), + ) + pub_sub_server_pixel_update = sgqlc.types.Field( + "PubSubServerPixelUpdatePayload", + graphql_name="pubSubServerPixelUpdate", + args=sgqlc.types.ArgDict( + ( + ("pub_sub_project", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="pubSubProject", default=None)), + ("pub_sub_topic", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="pubSubTopic", default=None)), ) ), ) @@ -13648,17 +16239,10 @@ class Mutation(sgqlc.types.Type): graphql_name="pubSubWebhookSubscriptionCreate", args=sgqlc.types.ArgDict( ( - ( - "topic", - sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None), - ), + ("topic", sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None)), ( "webhook_subscription", - sgqlc.types.Arg( - sgqlc.types.non_null(PubSubWebhookSubscriptionInput), - graphql_name="webhookSubscription", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(PubSubWebhookSubscriptionInput), graphql_name="webhookSubscription", default=None), ), ) ), @@ -13669,10 +16253,29 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "webhook_subscription", - sgqlc.types.Arg(PubSubWebhookSubscriptionInput, graphql_name="webhookSubscription", default=None), - ), + ("webhook_subscription", sgqlc.types.Arg(PubSubWebhookSubscriptionInput, graphql_name="webhookSubscription", default=None)), + ) + ), + ) + publication_create = sgqlc.types.Field( + "PublicationCreatePayload", + graphql_name="publicationCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(PublicationCreateInput), graphql_name="input", default=None)),) + ), + ) + publication_delete = sgqlc.types.Field( + "PublicationDeletePayload", + graphql_name="publicationDelete", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + publication_update = sgqlc.types.Field( + "PublicationUpdatePayload", + graphql_name="publicationUpdate", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(PublicationUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -13720,47 +16323,175 @@ class Mutation(sgqlc.types.Type): graphql_name="publishableUnpublishToCurrentChannel", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + quantity_rules_add = sgqlc.types.Field( + "QuantityRulesAddPayload", + graphql_name="quantityRulesAdd", + args=sgqlc.types.ArgDict( + ( + ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), + ( + "quantity_rules", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(QuantityRuleInput))), + graphql_name="quantityRules", + default=None, + ), + ), + ) + ), + ) + quantity_rules_delete = sgqlc.types.Field( + "QuantityRulesDeletePayload", + graphql_name="quantityRulesDelete", + args=sgqlc.types.ArgDict( + ( + ("price_list_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="priceListId", default=None)), + ( + "variant_ids", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="variantIds", default=None + ), + ), + ) + ), + ) refund_create = sgqlc.types.Field( "RefundCreatePayload", graphql_name="refundCreate", args=sgqlc.types.ArgDict((("input", sgqlc.types.Arg(sgqlc.types.non_null(RefundInput), graphql_name="input", default=None)),)), ) - saved_search_create = sgqlc.types.Field( - "SavedSearchCreatePayload", - graphql_name="savedSearchCreate", + return_approve_request = sgqlc.types.Field( + "ReturnApproveRequestPayload", + graphql_name="returnApproveRequest", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(ReturnApproveRequestInput), graphql_name="input", default=None)),) + ), + ) + return_cancel = sgqlc.types.Field( + "ReturnCancelPayload", + graphql_name="returnCancel", + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ("notify_customer", sgqlc.types.Arg(Boolean, graphql_name="notifyCustomer", default=False)), + ) + ), + ) + return_close = sgqlc.types.Field( + "ReturnClosePayload", + graphql_name="returnClose", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + return_create = sgqlc.types.Field( + "ReturnCreatePayload", + graphql_name="returnCreate", + args=sgqlc.types.ArgDict( + (("return_input", sgqlc.types.Arg(sgqlc.types.non_null(ReturnInput), graphql_name="returnInput", default=None)),) + ), + ) + return_decline_request = sgqlc.types.Field( + "ReturnDeclineRequestPayload", + graphql_name="returnDeclineRequest", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(ReturnDeclineRequestInput), graphql_name="input", default=None)),) + ), + ) + return_refund = sgqlc.types.Field( + "ReturnRefundPayload", + graphql_name="returnRefund", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchCreateInput), graphql_name="input", default=None), + "return_refund_input", + sgqlc.types.Arg(sgqlc.types.non_null(ReturnRefundInput), graphql_name="returnRefundInput", default=None), ), ) ), ) - saved_search_delete = sgqlc.types.Field( - "SavedSearchDeletePayload", - graphql_name="savedSearchDelete", + return_reopen = sgqlc.types.Field( + "ReturnReopenPayload", + graphql_name="returnReopen", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + return_request = sgqlc.types.Field( + "ReturnRequestPayload", + graphql_name="returnRequest", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(ReturnRequestInput), graphql_name="input", default=None)),) + ), + ) + reverse_delivery_create_with_shipping = sgqlc.types.Field( + "ReverseDeliveryCreateWithShippingPayload", + graphql_name="reverseDeliveryCreateWithShipping", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchDeleteInput), graphql_name="input", default=None), + "reverse_fulfillment_order_id", + sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="reverseFulfillmentOrderId", default=None), + ), + ( + "reverse_delivery_line_items", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ReverseDeliveryLineItemInput))), + graphql_name="reverseDeliveryLineItems", + default=None, + ), ), + ("tracking_input", sgqlc.types.Arg(ReverseDeliveryTrackingInput, graphql_name="trackingInput", default=None)), + ("label_input", sgqlc.types.Arg(ReverseDeliveryLabelInput, graphql_name="labelInput", default=None)), + ("notify_customer", sgqlc.types.Arg(Boolean, graphql_name="notifyCustomer", default=True)), ) ), ) - saved_search_update = sgqlc.types.Field( - "SavedSearchUpdatePayload", - graphql_name="savedSearchUpdate", + reverse_delivery_shipping_update = sgqlc.types.Field( + "ReverseDeliveryShippingUpdatePayload", + graphql_name="reverseDeliveryShippingUpdate", + args=sgqlc.types.ArgDict( + ( + ("reverse_delivery_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="reverseDeliveryId", default=None)), + ("tracking_input", sgqlc.types.Arg(ReverseDeliveryTrackingInput, graphql_name="trackingInput", default=None)), + ("label_input", sgqlc.types.Arg(ReverseDeliveryLabelInput, graphql_name="labelInput", default=None)), + ("notify_customer", sgqlc.types.Arg(Boolean, graphql_name="notifyCustomer", default=True)), + ) + ), + ) + reverse_fulfillment_order_dispose = sgqlc.types.Field( + "ReverseFulfillmentOrderDisposePayload", + graphql_name="reverseFulfillmentOrderDispose", args=sgqlc.types.ArgDict( ( ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchUpdateInput), graphql_name="input", default=None), + "disposition_inputs", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ReverseFulfillmentOrderDisposeInput))), + graphql_name="dispositionInputs", + default=None, + ), ), ) ), ) + saved_search_create = sgqlc.types.Field( + "SavedSearchCreatePayload", + graphql_name="savedSearchCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchCreateInput), graphql_name="input", default=None)),) + ), + ) + saved_search_delete = sgqlc.types.Field( + "SavedSearchDeletePayload", + graphql_name="savedSearchDelete", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchDeleteInput), graphql_name="input", default=None)),) + ), + ) + saved_search_update = sgqlc.types.Field( + "SavedSearchUpdatePayload", + graphql_name="savedSearchUpdate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(SavedSearchUpdateInput), graphql_name="input", default=None)),) + ), + ) script_tag_create = sgqlc.types.Field( "ScriptTagCreatePayload", graphql_name="scriptTagCreate", @@ -13816,9 +16547,7 @@ class Mutation(sgqlc.types.Type): ( "product_variant_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productVariantIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productVariantIds", default=None ), ), ) @@ -13833,9 +16562,7 @@ class Mutation(sgqlc.types.Type): ( "product_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productIds", default=None ), ), ) @@ -13846,10 +16573,7 @@ class Mutation(sgqlc.types.Type): graphql_name="sellingPlanGroupCreate", args=sgqlc.types.ArgDict( ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SellingPlanGroupInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SellingPlanGroupInput), graphql_name="input", default=None)), ("resources", sgqlc.types.Arg(SellingPlanGroupResourceInput, graphql_name="resources", default=None)), ) ), @@ -13868,9 +16592,7 @@ class Mutation(sgqlc.types.Type): ( "product_variant_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productVariantIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productVariantIds", default=None ), ), ) @@ -13885,9 +16607,7 @@ class Mutation(sgqlc.types.Type): ( "product_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="productIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="productIds", default=None ), ), ) @@ -13899,10 +16619,12 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ("input", sgqlc.types.Arg(SellingPlanGroupInput, graphql_name="input", default=None)), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SellingPlanGroupInput), graphql_name="input", default=None)), ) ), ) + server_pixel_create = sgqlc.types.Field("ServerPixelCreatePayload", graphql_name="serverPixelCreate") + server_pixel_delete = sgqlc.types.Field("ServerPixelDeletePayload", graphql_name="serverPixelDelete") shipping_package_delete = sgqlc.types.Field( "ShippingPackageDeletePayload", graphql_name="shippingPackageDelete", @@ -13916,7 +16638,15 @@ class Mutation(sgqlc.types.Type): shipping_package_update = sgqlc.types.Field( "ShippingPackageUpdatePayload", graphql_name="shippingPackageUpdate", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + args=sgqlc.types.ArgDict( + ( + ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), + ( + "shipping_package", + sgqlc.types.Arg(sgqlc.types.non_null(CustomShippingPackageInput), graphql_name="shippingPackage", default=None), + ), + ) + ), ) shop_locale_disable = sgqlc.types.Field( "ShopLocaleDisablePayload", @@ -13942,10 +16672,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("locale", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="locale", default=None)), - ( - "shop_locale", - sgqlc.types.Arg(sgqlc.types.non_null(ShopLocaleInput), graphql_name="shopLocale", default=None), - ), + ("shop_locale", sgqlc.types.Arg(sgqlc.types.non_null(ShopLocaleInput), graphql_name="shopLocale", default=None)), ) ), ) @@ -13953,12 +16680,14 @@ class Mutation(sgqlc.types.Type): "ShopPolicyUpdatePayload", graphql_name="shopPolicyUpdate", args=sgqlc.types.ArgDict( - ( - ( - "shop_policy", - sgqlc.types.Arg(sgqlc.types.non_null(ShopPolicyInput), graphql_name="shopPolicy", default=None), - ), - ) + (("shop_policy", sgqlc.types.Arg(sgqlc.types.non_null(ShopPolicyInput), graphql_name="shopPolicy", default=None)),) + ), + ) + shop_resource_feedback_create = sgqlc.types.Field( + "ShopResourceFeedbackCreatePayload", + graphql_name="shopResourceFeedbackCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(ResourceFeedbackCreateInput), graphql_name="input", default=None)),) ), ) staged_uploads_create = sgqlc.types.Field( @@ -13982,43 +16711,33 @@ class Mutation(sgqlc.types.Type): graphql_name="standardMetafieldDefinitionEnable", args=sgqlc.types.ArgDict( ( - ( - "owner_type", - sgqlc.types.Arg(sgqlc.types.non_null(MetafieldOwnerType), graphql_name="ownerType", default=None), - ), + ("owner_type", sgqlc.types.Arg(sgqlc.types.non_null(MetafieldOwnerType), graphql_name="ownerType", default=None)), ("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)), ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), ("key", sgqlc.types.Arg(String, graphql_name="key", default=None)), ("pin", sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="pin", default=False)), - ( - "visible_to_storefront_api", - sgqlc.types.Arg(Boolean, graphql_name="visibleToStorefrontApi", default=None), - ), + ("visible_to_storefront_api", sgqlc.types.Arg(Boolean, graphql_name="visibleToStorefrontApi", default=None)), + ("use_as_collection_condition", sgqlc.types.Arg(Boolean, graphql_name="useAsCollectionCondition", default=False)), ) ), ) + standard_metaobject_definition_enable = sgqlc.types.Field( + "StandardMetaobjectDefinitionEnablePayload", + graphql_name="standardMetaobjectDefinitionEnable", + args=sgqlc.types.ArgDict((("type", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="type", default=None)),)), + ) storefront_access_token_create = sgqlc.types.Field( "StorefrontAccessTokenCreatePayload", graphql_name="storefrontAccessTokenCreate", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(StorefrontAccessTokenInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(StorefrontAccessTokenInput), graphql_name="input", default=None)),) ), ) storefront_access_token_delete = sgqlc.types.Field( "StorefrontAccessTokenDeletePayload", graphql_name="storefrontAccessTokenDelete", args=sgqlc.types.ArgDict( - ( - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(StorefrontAccessTokenDeleteInput), graphql_name="input", default=None), - ), - ) + (("input", sgqlc.types.Arg(sgqlc.types.non_null(StorefrontAccessTokenDeleteInput), graphql_name="input", default=None)),) ), ) subscription_billing_attempt_create = sgqlc.types.Field( @@ -14033,9 +16752,7 @@ class Mutation(sgqlc.types.Type): ( "subscription_billing_attempt_input", sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingAttemptInput), - graphql_name="subscriptionBillingAttemptInput", - default=None, + sgqlc.types.non_null(SubscriptionBillingAttemptInput), graphql_name="subscriptionBillingAttemptInput", default=None ), ), ) @@ -14070,11 +16787,7 @@ class Mutation(sgqlc.types.Type): ( ( "billing_cycle_input", - sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCycleInput), - graphql_name="billingCycleInput", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionBillingCycleInput), graphql_name="billingCycleInput", default=None), ), ) ), @@ -14086,11 +16799,7 @@ class Mutation(sgqlc.types.Type): ( ( "billing_cycle_input", - sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCycleInput), - graphql_name="billingCycleInput", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionBillingCycleInput), graphql_name="billingCycleInput", default=None), ), ) ), @@ -14104,9 +16813,7 @@ class Mutation(sgqlc.types.Type): ( "target_selection", sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCyclesTargetSelection), - graphql_name="targetSelection", - default=None, + sgqlc.types.non_null(SubscriptionBillingCyclesTargetSelection), graphql_name="targetSelection", default=None ), ), ) @@ -14119,31 +16826,42 @@ class Mutation(sgqlc.types.Type): ( ( "billing_cycle_input", - sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCycleInput), - graphql_name="billingCycleInput", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionBillingCycleInput), graphql_name="billingCycleInput", default=None), ), ( "input", - sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCycleScheduleEditInput), - graphql_name="input", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionBillingCycleScheduleEditInput), graphql_name="input", default=None), ), ) ), ) + subscription_contract_atomic_create = sgqlc.types.Field( + "SubscriptionContractAtomicCreatePayload", + graphql_name="subscriptionContractAtomicCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionContractAtomicCreateInput), graphql_name="input", default=None)),) + ), + ) subscription_contract_create = sgqlc.types.Field( "SubscriptionContractCreatePayload", graphql_name="subscriptionContractCreate", + args=sgqlc.types.ArgDict( + (("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionContractCreateInput), graphql_name="input", default=None)),) + ), + ) + subscription_contract_product_change = sgqlc.types.Field( + "SubscriptionContractProductChangePayload", + graphql_name="subscriptionContractProductChange", args=sgqlc.types.ArgDict( ( + ( + "subscription_contract_id", + sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="subscriptionContractId", default=None), + ), + ("line_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="lineId", default=None)), ( "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionContractCreateInput), graphql_name="input", default=None), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionContractProductChangeInput), graphql_name="input", default=None), ), ) ), @@ -14174,10 +16892,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionManualDiscountInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionManualDiscountInput), graphql_name="input", default=None)), ) ), ) @@ -14208,10 +16923,7 @@ class Mutation(sgqlc.types.Type): ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), ("discount_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="discountId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionManualDiscountInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionManualDiscountInput), graphql_name="input", default=None)), ) ), ) @@ -14221,10 +16933,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionFreeShippingDiscountInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionFreeShippingDiscountInput), graphql_name="input", default=None)), ) ), ) @@ -14235,10 +16944,7 @@ class Mutation(sgqlc.types.Type): ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), ("discount_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="discountId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionFreeShippingDiscountInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionFreeShippingDiscountInput), graphql_name="input", default=None)), ) ), ) @@ -14248,10 +16954,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionLineInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionLineInput), graphql_name="input", default=None)), ) ), ) @@ -14272,10 +16975,7 @@ class Mutation(sgqlc.types.Type): ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), ("line_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="lineId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionLineUpdateInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionLineUpdateInput), graphql_name="input", default=None)), ) ), ) @@ -14285,10 +16985,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("draft_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="draftId", default=None)), - ( - "input", - sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionDraftInput), graphql_name="input", default=None), - ), + ("input", sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionDraftInput), graphql_name="input", default=None)), ) ), ) @@ -14301,9 +16998,7 @@ class Mutation(sgqlc.types.Type): ( "tags", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="tags", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags", default=None ), ), ) @@ -14318,14 +17013,17 @@ class Mutation(sgqlc.types.Type): ( "tags", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="tags", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags", default=None ), ), ) ), ) + tax_app_configure = sgqlc.types.Field( + "TaxAppConfigurePayload", + graphql_name="taxAppConfigure", + args=sgqlc.types.ArgDict((("ready", sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="ready", default=None)),)), + ) translations_register = sgqlc.types.Field( "TranslationsRegisterPayload", graphql_name="translationsRegister", @@ -14360,15 +17058,10 @@ class Mutation(sgqlc.types.Type): ( "locales", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="locales", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="locales", default=None ), ), - ( - "market_ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="marketIds", default=None), - ), + ("market_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="marketIds", default=None)), ) ), ) @@ -14380,11 +17073,7 @@ class Mutation(sgqlc.types.Type): ( ( "ids", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="ids", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="ids", default=None), ), ) ), @@ -14393,12 +17082,7 @@ class Mutation(sgqlc.types.Type): "UrlRedirectBulkDeleteBySavedSearchPayload", graphql_name="urlRedirectBulkDeleteBySavedSearch", args=sgqlc.types.ArgDict( - ( - ( - "saved_search_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="savedSearchId", default=None), - ), - ) + (("saved_search_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="savedSearchId", default=None)),) ), ) url_redirect_bulk_delete_by_search = sgqlc.types.Field( @@ -14410,12 +17094,7 @@ class Mutation(sgqlc.types.Type): "UrlRedirectCreatePayload", graphql_name="urlRedirectCreate", args=sgqlc.types.ArgDict( - ( - ( - "url_redirect", - sgqlc.types.Arg(sgqlc.types.non_null(UrlRedirectInput), graphql_name="urlRedirect", default=None), - ), - ) + (("url_redirect", sgqlc.types.Arg(sgqlc.types.non_null(UrlRedirectInput), graphql_name="urlRedirect", default=None)),) ), ) url_redirect_delete = sgqlc.types.Field( @@ -14439,10 +17118,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "url_redirect", - sgqlc.types.Arg(sgqlc.types.non_null(UrlRedirectInput), graphql_name="urlRedirect", default=None), - ), + ("url_redirect", sgqlc.types.Arg(sgqlc.types.non_null(UrlRedirectInput), graphql_name="urlRedirect", default=None)), ) ), ) @@ -14450,12 +17126,7 @@ class Mutation(sgqlc.types.Type): "WebPixelCreatePayload", graphql_name="webPixelCreate", args=sgqlc.types.ArgDict( - ( - ( - "web_pixel", - sgqlc.types.Arg(sgqlc.types.non_null(WebPixelInput), graphql_name="webPixel", default=None), - ), - ) + (("web_pixel", sgqlc.types.Arg(sgqlc.types.non_null(WebPixelInput), graphql_name="webPixel", default=None)),) ), ) web_pixel_delete = sgqlc.types.Field( @@ -14469,10 +17140,7 @@ class Mutation(sgqlc.types.Type): args=sgqlc.types.ArgDict( ( ("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)), - ( - "web_pixel", - sgqlc.types.Arg(sgqlc.types.non_null(WebPixelInput), graphql_name="webPixel", default=None), - ), + ("web_pixel", sgqlc.types.Arg(sgqlc.types.non_null(WebPixelInput), graphql_name="webPixel", default=None)), ) ), ) @@ -14481,10 +17149,7 @@ class Mutation(sgqlc.types.Type): graphql_name="webhookSubscriptionCreate", args=sgqlc.types.ArgDict( ( - ( - "topic", - sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None), - ), + ("topic", sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic", default=None)), ( "webhook_subscription", sgqlc.types.Arg(sgqlc.types.non_null(WebhookSubscriptionInput), graphql_name="webhookSubscription", default=None), @@ -14514,15 +17179,9 @@ class Mutation(sgqlc.types.Type): class MutationsStagedUploadTargetGenerateUploadParameter(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("name", "value") - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - value = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="value") - - -class Navigable(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("default_cursor",) - default_cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="defaultCursor") + __field_names__ = ("name", "value") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + value = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="value") class NavigationItem(sgqlc.types.Type): @@ -14533,18 +17192,6 @@ class NavigationItem(sgqlc.types.Type): url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") -class Node(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("id",) - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - - -class OnlineStorePreviewable(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("online_store_preview_url",) - online_store_preview_url = sgqlc.types.Field(URL, graphql_name="onlineStorePreviewUrl") - - class OrderApp(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("icon", "id", "name") @@ -14581,8 +17228,7 @@ class OrderCreateMandatePaymentPayload(sgqlc.types.Type): job = sgqlc.types.Field(Job, graphql_name="job") payment_reference_id = sgqlc.types.Field(String, graphql_name="paymentReferenceId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderCreateMandatePaymentUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderCreateMandatePaymentUserError"))), graphql_name="userErrors" ) @@ -14653,8 +17299,7 @@ class OrderInvoiceSendPayload(sgqlc.types.Type): __field_names__ = ("order", "user_errors") order = sgqlc.types.Field("Order", graphql_name="order") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderInvoiceSendUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderInvoiceSendUserError"))), graphql_name="userErrors" ) @@ -14793,6 +17438,83 @@ class PageInfo(sgqlc.types.Type): start_cursor = sgqlc.types.Field(String, graphql_name="startCursor") +class ParseError(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("code", "message", "range") + code = sgqlc.types.Field(sgqlc.types.non_null(ParseErrorCode), graphql_name="code") + message = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="message") + range = sgqlc.types.Field("ParseErrorRange", graphql_name="range") + + +class ParseErrorRange(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("end", "start") + end = sgqlc.types.Field(sgqlc.types.non_null(ErrorPosition), graphql_name="end") + start = sgqlc.types.Field(sgqlc.types.non_null(ErrorPosition), graphql_name="start") + + +class PaymentCustomizationActivationPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("ids", "user_errors") + ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="ids") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomizationError"))), graphql_name="userErrors" + ) + + +class PaymentCustomizationConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomizationEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomization"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class PaymentCustomizationCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("payment_customization", "user_errors") + payment_customization = sgqlc.types.Field("PaymentCustomization", graphql_name="paymentCustomization") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomizationError"))), graphql_name="userErrors" + ) + + +class PaymentCustomizationDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomizationError"))), graphql_name="userErrors" + ) + + +class PaymentCustomizationEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("PaymentCustomization"), graphql_name="node") + + +class PaymentCustomizationUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("payment_customization", "user_errors") + payment_customization = sgqlc.types.Field("PaymentCustomization", graphql_name="paymentCustomization") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentCustomizationError"))), graphql_name="userErrors" + ) + + +class PaymentReminderSendPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("success", "user_errors") + success = sgqlc.types.Field(Boolean, graphql_name="success") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentReminderSendUserError"))), graphql_name="userErrors" + ) + + class PaymentScheduleConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -14812,8 +17534,7 @@ class PaymentSettings(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("supported_digital_wallets",) supported_digital_wallets = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DigitalWallet))), - graphql_name="supportedDigitalWallets", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DigitalWallet))), graphql_name="supportedDigitalWallets" ) @@ -14822,8 +17543,7 @@ class PaymentTermsCreatePayload(sgqlc.types.Type): __field_names__ = ("payment_terms", "user_errors") payment_terms = sgqlc.types.Field("PaymentTerms", graphql_name="paymentTerms") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsCreateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsCreateUserError"))), graphql_name="userErrors" ) @@ -14832,8 +17552,7 @@ class PaymentTermsDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_id", "user_errors") deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsDeleteUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsDeleteUserError"))), graphql_name="userErrors" ) @@ -14842,11 +17561,25 @@ class PaymentTermsUpdatePayload(sgqlc.types.Type): __field_names__ = ("payment_terms", "user_errors") payment_terms = sgqlc.types.Field("PaymentTerms", graphql_name="paymentTerms") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsUpdateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsUpdateUserError"))), graphql_name="userErrors" ) +class PolarisVizDataPoint(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("key", "value") + key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") + value = sgqlc.types.Field(String, graphql_name="value") + + +class PolarisVizDataSeries(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("data", "is_comparison", "name") + data = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(PolarisVizDataPoint))), graphql_name="data") + is_comparison = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isComparison") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + + class PriceListAdjustment(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("type", "value") @@ -14854,6 +17587,12 @@ class PriceListAdjustment(sgqlc.types.Type): value = sgqlc.types.Field(sgqlc.types.non_null(Float), graphql_name="value") +class PriceListAdjustmentSettings(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("compare_at_mode",) + compare_at_mode = sgqlc.types.Field(sgqlc.types.non_null(PriceListCompareAtMode), graphql_name="compareAtMode") + + class PriceListConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -14862,13 +17601,6 @@ class PriceListConnection(sgqlc.types.relay.Connection): page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class PriceListContextRule(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("countries", "market") - countries = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CountryCode))), graphql_name="countries") - market = sgqlc.types.Field("Market", graphql_name="market") - - class PriceListCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("price_list", "user_errors") @@ -14899,7 +17631,20 @@ class PriceListFixedPricesAddPayload(sgqlc.types.Type): __field_names__ = ("prices", "user_errors") prices = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPrice")), graphql_name="prices") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPriceUserError"))), + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPriceUserError"))), graphql_name="userErrors" + ) + + +class PriceListFixedPricesByProductUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("price_list", "prices_to_add_products", "prices_to_delete_products", "user_errors") + price_list = sgqlc.types.Field("PriceList", graphql_name="priceList") + prices_to_add_products = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("Product")), graphql_name="pricesToAddProducts") + prices_to_delete_products = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("Product")), graphql_name="pricesToDeleteProducts" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListFixedPricesByProductBulkUpdateUserError"))), graphql_name="userErrors", ) @@ -14911,15 +17656,28 @@ class PriceListFixedPricesDeletePayload(sgqlc.types.Type): sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedFixedPriceVariantIds" ) user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPriceUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPriceUserError"))), graphql_name="userErrors" + ) + + +class PriceListFixedPricesUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_fixed_price_variant_ids", "price_list", "prices_added", "user_errors") + deleted_fixed_price_variant_ids = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedFixedPriceVariantIds" + ) + price_list = sgqlc.types.Field("PriceList", graphql_name="priceList") + prices_added = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPrice")), graphql_name="pricesAdded") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceListPriceUserError"))), graphql_name="userErrors" ) class PriceListParent(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("adjustment",) + __field_names__ = ("adjustment", "settings") adjustment = sgqlc.types.Field(sgqlc.types.non_null(PriceListAdjustment), graphql_name="adjustment") + settings = sgqlc.types.Field(sgqlc.types.non_null(PriceListAdjustmentSettings), graphql_name="settings") class PriceListPrice(sgqlc.types.Type): @@ -14960,8 +17718,7 @@ class PriceRuleActivatePayload(sgqlc.types.Type): __field_names__ = ("price_rule", "price_rule_user_errors") price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -14979,8 +17736,7 @@ class PriceRuleCreatePayload(sgqlc.types.Type): price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_discount_code = sgqlc.types.Field("PriceRuleDiscountCode", graphql_name="priceRuleDiscountCode") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -15012,8 +17768,7 @@ class PriceRuleDeactivatePayload(sgqlc.types.Type): __field_names__ = ("price_rule", "price_rule_user_errors") price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -15022,8 +17777,7 @@ class PriceRuleDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_price_rule_id", "price_rule_user_errors", "shop") deleted_price_rule_id = sgqlc.types.Field(ID, graphql_name="deletedPriceRuleId") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) shop = sgqlc.types.Field(sgqlc.types.non_null("Shop"), graphql_name="shop") @@ -15032,8 +17786,7 @@ class PriceRuleDiscountCodeConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleDiscountCodeEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleDiscountCodeEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleDiscountCode"))), graphql_name="nodes" @@ -15047,8 +17800,7 @@ class PriceRuleDiscountCodeCreatePayload(sgqlc.types.Type): price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_discount_code = sgqlc.types.Field("PriceRuleDiscountCode", graphql_name="priceRuleDiscountCode") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -15065,8 +17817,7 @@ class PriceRuleDiscountCodeUpdatePayload(sgqlc.types.Type): price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_discount_code = sgqlc.types.Field("PriceRuleDiscountCode", graphql_name="priceRuleDiscountCode") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -15235,8 +17986,7 @@ class PriceRuleUpdatePayload(sgqlc.types.Type): price_rule = sgqlc.types.Field("PriceRule", graphql_name="priceRule") price_rule_discount_code = sgqlc.types.Field("PriceRuleDiscountCode", graphql_name="priceRuleDiscountCode") price_rule_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), - graphql_name="priceRuleUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PriceRuleUserError"))), graphql_name="priceRuleUserErrors" ) @@ -15301,8 +18051,7 @@ class ProductChangeStatusPayload(sgqlc.types.Type): __field_names__ = ("product", "user_errors") product = sgqlc.types.Field("Product", graphql_name="product") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductChangeStatusUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductChangeStatusUserError"))), graphql_name="userErrors" ) @@ -15316,7 +18065,8 @@ class ProductConnection(sgqlc.types.relay.Connection): class ProductContextualPricing(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("max_variant_pricing", "min_variant_pricing", "price_range") + __field_names__ = ("fixed_quantity_rules_count", "max_variant_pricing", "min_variant_pricing", "price_range") + fixed_quantity_rules_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="fixedQuantityRulesCount") max_variant_pricing = sgqlc.types.Field("ProductVariantContextualPricing", graphql_name="maxVariantPricing") min_variant_pricing = sgqlc.types.Field("ProductVariantContextualPricing", graphql_name="minVariantPricing") price_range = sgqlc.types.Field(sgqlc.types.non_null("ProductPriceRangeV2"), graphql_name="priceRange") @@ -15327,8 +18077,7 @@ class ProductCreateMediaPayload(sgqlc.types.Type): __field_names__ = ("media", "media_user_errors", "product") media = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(Media)), graphql_name="media") media_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), - graphql_name="mediaUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), graphql_name="mediaUserErrors" ) product = sgqlc.types.Field("Product", graphql_name="product") @@ -15341,6 +18090,16 @@ class ProductCreatePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class ProductDeleteAsyncPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("delete_product_id", "job", "user_errors") + delete_product_id = sgqlc.types.Field(ID, graphql_name="deleteProductId") + job = sgqlc.types.Field(Job, graphql_name="job") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductDeleteUserError"))), graphql_name="userErrors" + ) + + class ProductDeleteImagesPayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("deleted_image_ids", "product", "user_errors") @@ -15357,8 +18116,7 @@ class ProductDeleteMediaPayload(sgqlc.types.Type): deleted_media_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedMediaIds") deleted_product_image_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedProductImageIds") media_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), - graphql_name="mediaUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), graphql_name="mediaUserErrors" ) product = sgqlc.types.Field("Product", graphql_name="product") @@ -15371,6 +18129,33 @@ class ProductDeletePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class ProductDuplicateAsyncPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("duplicated_product_id", "job", "user_errors") + duplicated_product_id = sgqlc.types.Field(ID, graphql_name="duplicatedProductId") + job = sgqlc.types.Field(Job, graphql_name="job") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductDuplicateUserError"))), graphql_name="userErrors" + ) + + +class ProductDuplicateAsyncV2Payload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("duplicated_product_id", "product_duplicate_job_id", "user_errors") + duplicated_product_id = sgqlc.types.Field(ID, graphql_name="duplicatedProductId") + product_duplicate_job_id = sgqlc.types.Field(ID, graphql_name="productDuplicateJobId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductDuplicateUserError"))), graphql_name="userErrors" + ) + + +class ProductDuplicateJob(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("done", "id") + done = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="done") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + + class ProductDuplicatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("image_job", "new_product", "shop", "user_errors") @@ -15387,6 +18172,47 @@ class ProductEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("Product"), graphql_name="node") +class ProductFeedConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductFeedEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductFeed"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ProductFeedCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("product_feed", "user_errors") + product_feed = sgqlc.types.Field("ProductFeed", graphql_name="productFeed") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductFeedCreateUserError"))), graphql_name="userErrors" + ) + + +class ProductFeedDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductFeedDeleteUserError"))), graphql_name="userErrors" + ) + + +class ProductFeedEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ProductFeed"), graphql_name="node") + + +class ProductFullSyncPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("user_errors",) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductFullSyncUserError"))), graphql_name="userErrors" + ) + + class ProductImageUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("image", "user_errors") @@ -15399,8 +18225,7 @@ class ProductJoinSellingPlanGroupsPayload(sgqlc.types.Type): __field_names__ = ("product", "user_errors") product = sgqlc.types.Field("Product", graphql_name="product") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -15409,8 +18234,7 @@ class ProductLeaveSellingPlanGroupsPayload(sgqlc.types.Type): __field_names__ = ("product", "user_errors") product = sgqlc.types.Field("Product", graphql_name="product") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -15474,8 +18298,7 @@ class ProductReorderMediaPayload(sgqlc.types.Type): __field_names__ = ("job", "media_user_errors") job = sgqlc.types.Field(Job, graphql_name="job") media_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), - graphql_name="mediaUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), graphql_name="mediaUserErrors" ) @@ -15502,8 +18325,7 @@ class ProductUpdateMediaPayload(sgqlc.types.Type): __field_names__ = ("media", "media_user_errors", "product") media = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(Media)), graphql_name="media") media_user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), - graphql_name="mediaUserErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MediaUserError"))), graphql_name="mediaUserErrors" ) product = sgqlc.types.Field("Product", graphql_name="product") @@ -15525,6 +18347,25 @@ class ProductVariantAppendMediaPayload(sgqlc.types.Type): ) +class ProductVariantComponentConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantComponentEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantComponent"))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ProductVariantComponentEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ProductVariantComponent"), graphql_name="node") + + class ProductVariantConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -15535,9 +18376,10 @@ class ProductVariantConnection(sgqlc.types.relay.Connection): class ProductVariantContextualPricing(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("compare_at_price", "price") + __field_names__ = ("compare_at_price", "price", "quantity_rule") compare_at_price = sgqlc.types.Field(MoneyV2, graphql_name="compareAtPrice") price = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="price") + quantity_rule = sgqlc.types.Field(sgqlc.types.non_null("QuantityRule"), graphql_name="quantityRule") class ProductVariantCreatePayload(sgqlc.types.Type): @@ -15578,8 +18420,7 @@ class ProductVariantJoinSellingPlanGroupsPayload(sgqlc.types.Type): __field_names__ = ("product_variant", "user_errors") product_variant = sgqlc.types.Field("ProductVariant", graphql_name="productVariant") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -15588,8 +18429,7 @@ class ProductVariantLeaveSellingPlanGroupsPayload(sgqlc.types.Type): __field_names__ = ("product_variant", "user_errors") product_variant = sgqlc.types.Field("ProductVariant", graphql_name="productVariant") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -15604,8 +18444,7 @@ class ProductVariantPricePairConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantPricePairEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantPricePairEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductVariantPricePair))), graphql_name="nodes" @@ -15620,6 +18459,18 @@ class ProductVariantPricePairEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null(ProductVariantPricePair), graphql_name="node") +class ProductVariantRelationshipBulkUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("parent_product_variants", "user_errors") + parent_product_variants = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("ProductVariant")), graphql_name="parentProductVariants" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantRelationshipBulkUpdateUserError"))), + graphql_name="userErrors", + ) + + class ProductVariantUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("product", "product_variant", "user_errors") @@ -15634,8 +18485,7 @@ class ProductVariantsBulkCreatePayload(sgqlc.types.Type): product = sgqlc.types.Field("Product", graphql_name="product") product_variants = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariant")), graphql_name="productVariants") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkCreateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkCreateUserError"))), graphql_name="userErrors" ) @@ -15644,8 +18494,7 @@ class ProductVariantsBulkDeletePayload(sgqlc.types.Type): __field_names__ = ("product", "user_errors") product = sgqlc.types.Field("Product", graphql_name="product") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkDeleteUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkDeleteUserError"))), graphql_name="userErrors" ) @@ -15654,8 +18503,7 @@ class ProductVariantsBulkReorderPayload(sgqlc.types.Type): __field_names__ = ("product", "user_errors") product = sgqlc.types.Field("Product", graphql_name="product") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkReorderUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkReorderUserError"))), graphql_name="userErrors" ) @@ -15665,8 +18513,16 @@ class ProductVariantsBulkUpdatePayload(sgqlc.types.Type): product = sgqlc.types.Field("Product", graphql_name="product") product_variants = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariant")), graphql_name="productVariants") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkUpdateUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ProductVariantsBulkUpdateUserError"))), graphql_name="userErrors" + ) + + +class PubSubServerPixelUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("server_pixel", "user_errors") + server_pixel = sgqlc.types.Field("ServerPixel", graphql_name="serverPixel") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsServerPixelUserError"))), graphql_name="userErrors" ) @@ -15691,85 +18547,44 @@ class PubSubWebhookSubscriptionUpdatePayload(sgqlc.types.Type): class PublicationConnection(sgqlc.types.relay.Connection): - __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublicationEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Publication"))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") - - -class PublicationEdge(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="node") - - -class Publishable(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ( - "available_publication_count", - "publication_count", - "published_on_current_publication", - "published_on_publication", - "resource_publications", - "resource_publications_v2", - "unpublished_publications", - ) - available_publication_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="availablePublicationCount") - publication_count = sgqlc.types.Field( - sgqlc.types.non_null(Int), - graphql_name="publicationCount", - args=sgqlc.types.ArgDict((("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)),)), - ) - published_on_current_publication = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="publishedOnCurrentPublication") - published_on_publication = sgqlc.types.Field( - sgqlc.types.non_null(Boolean), - graphql_name="publishedOnPublication", - args=sgqlc.types.ArgDict( - (("publication_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="publicationId", default=None)),) - ), - ) - resource_publications = sgqlc.types.Field( - sgqlc.types.non_null("ResourcePublicationConnection"), - graphql_name="resourcePublications", - args=sgqlc.types.ArgDict( - ( - ("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - resource_publications_v2 = sgqlc.types.Field( - sgqlc.types.non_null("ResourcePublicationV2Connection"), - graphql_name="resourcePublicationsV2", - args=sgqlc.types.ArgDict( - ( - ("only_published", sgqlc.types.Arg(Boolean, graphql_name="onlyPublished", default=True)), - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublicationEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Publication"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class PublicationCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("publication", "user_errors") + publication = sgqlc.types.Field("Publication", graphql_name="publication") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublicationUserError"))), graphql_name="userErrors" ) - unpublished_publications = sgqlc.types.Field( - sgqlc.types.non_null(PublicationConnection), - graphql_name="unpublishedPublications", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), + + +class PublicationDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_id", "user_errors") + deleted_id = sgqlc.types.Field(ID, graphql_name="deletedId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublicationUserError"))), graphql_name="userErrors" + ) + + +class PublicationEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="node") + + +class PublicationUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("publication", "user_errors") + publication = sgqlc.types.Field("Publication", graphql_name="publication") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PublicationUserError"))), graphql_name="userErrors" ) @@ -15805,15 +18620,6 @@ class PublishableUnpublishToCurrentChannelPayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") -class PublishedTranslation(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("key", "locale", "market_id", "value") - key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") - locale = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="locale") - market_id = sgqlc.types.Field(ID, graphql_name="marketId") - value = sgqlc.types.Field(String, graphql_name="value") - - class PurchasingCompany(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("company", "contact", "location") @@ -15822,9 +18628,58 @@ class PurchasingCompany(sgqlc.types.Type): location = sgqlc.types.Field(sgqlc.types.non_null("CompanyLocation"), graphql_name="location") +class QuantityRule(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("increment", "is_default", "maximum", "minimum", "origin_type", "product_variant") + increment = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="increment") + is_default = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isDefault") + maximum = sgqlc.types.Field(Int, graphql_name="maximum") + minimum = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="minimum") + origin_type = sgqlc.types.Field(sgqlc.types.non_null(QuantityRuleOriginType), graphql_name="originType") + product_variant = sgqlc.types.Field(sgqlc.types.non_null("ProductVariant"), graphql_name="productVariant") + + +class QuantityRuleConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info", "total_count") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("QuantityRuleEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(QuantityRule))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + total_count = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="totalCount") + + +class QuantityRuleEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(QuantityRule), graphql_name="node") + + +class QuantityRulesAddPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("quantity_rules", "user_errors") + quantity_rules = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(QuantityRule)), graphql_name="quantityRules") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("QuantityRuleUserError"))), graphql_name="userErrors" + ) + + +class QuantityRulesDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_quantity_rules_variant_ids", "user_errors") + deleted_quantity_rules_variant_ids = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedQuantityRulesVariantIds" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("QuantityRuleUserError"))), graphql_name="userErrors" + ) + + class QueryRoot(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( + "abandonment", + "abandonment_by_abandoned_checkout_id", "app", "app_by_handle", "app_by_key", @@ -15838,6 +18693,10 @@ class QueryRoot(sgqlc.types.Type): "available_carrier_services", "available_locales", "carrier_service", + "cart_transforms", + "catalog", + "catalog_operations", + "catalogs", "checkout_profile", "checkout_profiles", "code_discount_node", @@ -15859,11 +18718,16 @@ class QueryRoot(sgqlc.types.Type): "current_app_installation", "current_bulk_operation", "customer", + "customer_merge_job_status", + "customer_merge_preview", "customer_payment_method", "customer_segment_members", + "customer_segment_members_query", "customer_segment_membership", "customers", "deletion_events", + "delivery_customization", + "delivery_customizations", "delivery_profile", "delivery_profiles", "delivery_settings", @@ -15883,6 +18747,7 @@ class QueryRoot(sgqlc.types.Type): "files", "fulfillment", "fulfillment_order", + "fulfillment_orders", "fulfillment_service", "gift_card", "gift_cards", @@ -15890,6 +18755,7 @@ class QueryRoot(sgqlc.types.Type): "inventory_item", "inventory_items", "inventory_level", + "inventory_properties", "job", "location", "locations", @@ -15909,25 +18775,30 @@ class QueryRoot(sgqlc.types.Type): "metafield_definition", "metafield_definition_types", "metafield_definitions", - "metafield_storefront_visibilities", - "metafield_storefront_visibility", + "metaobject", + "metaobject_by_handle", + "metaobject_definition", + "metaobject_definition_by_type", + "metaobject_definitions", + "metaobjects", "node", "nodes", "order", "order_payment_status", "order_saved_searches", "orders", + "payment_customization", + "payment_customizations", "payment_terms_templates", "price_list", "price_lists", - "price_rule", "price_rule_saved_searches", - "price_rules", "primary_market", - "private_metafield", - "private_metafields", "product", "product_by_handle", + "product_duplicate_job", + "product_feed", + "product_feeds", "product_resource_feedback", "product_saved_searches", "product_variant", @@ -15937,6 +18808,11 @@ class QueryRoot(sgqlc.types.Type): "publication", "publications", "refund", + "return_", + "returnable_fulfillment", + "returnable_fulfillments", + "reverse_delivery", + "reverse_fulfillment_order", "script_tag", "script_tags", "segment", @@ -15948,12 +18824,18 @@ class QueryRoot(sgqlc.types.Type): "segments", "selling_plan_group", "selling_plan_groups", + "server_pixel", "shop", + "shop_billing_preferences", "shop_locales", + "shopify_function", + "shopify_functions", "shopify_payments_account", + "shopifyql_query", "staff_member", "standard_metafield_definition_templates", "subscription_billing_attempt", + "subscription_billing_attempts", "subscription_billing_cycle", "subscription_billing_cycles", "subscription_contract", @@ -15971,10 +18853,20 @@ class QueryRoot(sgqlc.types.Type): "webhook_subscription", "webhook_subscriptions", ) + abandonment = sgqlc.types.Field( + "Abandonment", + graphql_name="abandonment", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + abandonment_by_abandoned_checkout_id = sgqlc.types.Field( + "Abandonment", + graphql_name="abandonmentByAbandonedCheckoutId", + args=sgqlc.types.ArgDict( + (("abandoned_checkout_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="abandonedCheckoutId", default=None)),) + ), + ) app = sgqlc.types.Field( - "App", - graphql_name="app", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)), + "App", graphql_name="app", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)) ) app_by_handle = sgqlc.types.Field( "App", @@ -15994,8 +18886,7 @@ class QueryRoot(sgqlc.types.Type): ), ) app_discount_types = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppDiscountType))), - graphql_name="appDiscountTypes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppDiscountType))), graphql_name="appDiscountTypes" ) app_installation = sgqlc.types.Field( "AppInstallation", @@ -16064,6 +18955,43 @@ class QueryRoot(sgqlc.types.Type): graphql_name="carrierService", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + cart_transforms = sgqlc.types.Field( + sgqlc.types.non_null(CartTransformConnection), + graphql_name="cartTransforms", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + catalog = sgqlc.types.Field( + Catalog, + graphql_name="catalog", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + catalog_operations = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourceOperation))), graphql_name="catalogOperations" + ) + catalogs = sgqlc.types.Field( + sgqlc.types.non_null(CatalogConnection), + graphql_name="catalogs", + args=sgqlc.types.ArgDict( + ( + ("type", sgqlc.types.Arg(CatalogType, graphql_name="type", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(CatalogSortKeys, graphql_name="sortKey", default="ID")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) checkout_profile = sgqlc.types.Field( "CheckoutProfile", graphql_name="checkoutProfile", @@ -16134,8 +19062,7 @@ class QueryRoot(sgqlc.types.Type): args=sgqlc.types.ArgDict((("handle", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="handle", default=None)),)), ) collection_rules_conditions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionRuleConditions))), - graphql_name="collectionRulesConditions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CollectionRuleConditions))), graphql_name="collectionRulesConditions" ) collection_saved_searches = sgqlc.types.Field( sgqlc.types.non_null("SavedSearchConnection"), @@ -16228,6 +19155,22 @@ class QueryRoot(sgqlc.types.Type): graphql_name="customer", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + customer_merge_job_status = sgqlc.types.Field( + CustomerMergeRequest, + graphql_name="customerMergeJobStatus", + args=sgqlc.types.ArgDict((("job_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="jobId", default=None)),)), + ) + customer_merge_preview = sgqlc.types.Field( + sgqlc.types.non_null(CustomerMergePreview), + graphql_name="customerMergePreview", + args=sgqlc.types.ArgDict( + ( + ("customer_one_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerOneId", default=None)), + ("customer_two_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerTwoId", default=None)), + ("override_fields", sgqlc.types.Arg(CustomerMergeOverrideFields, graphql_name="overrideFields", default=None)), + ) + ), + ) customer_payment_method = sgqlc.types.Field( "CustomerPaymentMethod", graphql_name="customerPaymentMethod", @@ -16245,6 +19188,7 @@ class QueryRoot(sgqlc.types.Type): ( ("segment_id", sgqlc.types.Arg(ID, graphql_name="segmentId", default=None)), ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ("query_id", sgqlc.types.Arg(ID, graphql_name="queryId", default=None)), ("timezone", sgqlc.types.Arg(String, graphql_name="timezone", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), ("sort_key", sgqlc.types.Arg(String, graphql_name="sortKey", default=None)), @@ -16255,6 +19199,11 @@ class QueryRoot(sgqlc.types.Type): ) ), ) + customer_segment_members_query = sgqlc.types.Field( + "CustomerSegmentMembersQuery", + graphql_name="customerSegmentMembersQuery", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) customer_segment_membership = sgqlc.types.Field( sgqlc.types.non_null("SegmentMembershipResponse"), graphql_name="customerSegmentMembership", @@ -16263,9 +19212,7 @@ class QueryRoot(sgqlc.types.Type): ( "segment_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="segmentIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="segmentIds", default=None ), ), ("customer_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="customerId", default=None)), @@ -16295,9 +19242,7 @@ class QueryRoot(sgqlc.types.Type): ( "subject_types", sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(DeletionEventSubjectType)), - graphql_name="subjectTypes", - default=None, + sgqlc.types.list_of(sgqlc.types.non_null(DeletionEventSubjectType)), graphql_name="subjectTypes", default=None ), ), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -16310,6 +19255,25 @@ class QueryRoot(sgqlc.types.Type): ) ), ) + delivery_customization = sgqlc.types.Field( + "DeliveryCustomization", + graphql_name="deliveryCustomization", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + delivery_customizations = sgqlc.types.Field( + sgqlc.types.non_null(DeliveryCustomizationConnection), + graphql_name="deliveryCustomizations", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) delivery_profile = sgqlc.types.Field( "DeliveryProfile", graphql_name="deliveryProfile", @@ -16469,6 +19433,22 @@ class QueryRoot(sgqlc.types.Type): graphql_name="fulfillmentOrder", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + fulfillment_orders = sgqlc.types.Field( + sgqlc.types.non_null(FulfillmentOrderConnection), + graphql_name="fulfillmentOrders", + args=sgqlc.types.ArgDict( + ( + ("include_closed", sgqlc.types.Arg(Boolean, graphql_name="includeClosed", default=False)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(FulfillmentOrderSortKeys, graphql_name="sortKey", default="ID")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) fulfillment_service = sgqlc.types.Field( FulfillmentService, graphql_name="fulfillmentService", @@ -16524,15 +19504,14 @@ class QueryRoot(sgqlc.types.Type): graphql_name="inventoryLevel", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + inventory_properties = sgqlc.types.Field(sgqlc.types.non_null(InventoryProperties), graphql_name="inventoryProperties") job = sgqlc.types.Field( Job, graphql_name="job", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) location = sgqlc.types.Field( - "Location", - graphql_name="location", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)), + "Location", graphql_name="location", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)) ) locations = sgqlc.types.Field( sgqlc.types.non_null(LocationConnection), @@ -16587,12 +19566,7 @@ class QueryRoot(sgqlc.types.Type): "Market", graphql_name="marketByGeography", args=sgqlc.types.ArgDict( - ( - ( - "country_code", - sgqlc.types.Arg(sgqlc.types.non_null(CountryCode), graphql_name="countryCode", default=None), - ), - ) + (("country_code", sgqlc.types.Arg(sgqlc.types.non_null(CountryCode), graphql_name="countryCode", default=None)),) ), ) market_localizable_resource = sgqlc.types.Field( @@ -16625,9 +19599,7 @@ class QueryRoot(sgqlc.types.Type): ( "resource_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="resourceIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="resourceIds", default=None ), ), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -16647,10 +19619,7 @@ class QueryRoot(sgqlc.types.Type): "marketing_activity_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="marketingActivityIds", default=()), ), - ( - "remote_ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="remoteIds", default=()), - ), + ("remote_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="remoteIds", default=())), ("utm", sgqlc.types.Arg(UTMInput, graphql_name="utm", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), @@ -16712,8 +19681,7 @@ class QueryRoot(sgqlc.types.Type): args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) metafield_definition_types = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionType))), - graphql_name="metafieldDefinitionTypes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionType))), graphql_name="metafieldDefinitionTypes" ) metafield_definitions = sgqlc.types.Field( sgqlc.types.non_null(MetafieldDefinitionConnection), @@ -16722,14 +19690,8 @@ class QueryRoot(sgqlc.types.Type): ( ("key", sgqlc.types.Arg(String, graphql_name="key", default=None)), ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), - ( - "owner_type", - sgqlc.types.Arg(sgqlc.types.non_null(MetafieldOwnerType), graphql_name="ownerType", default=None), - ), - ( - "pinned_status", - sgqlc.types.Arg(MetafieldDefinitionPinnedStatus, graphql_name="pinnedStatus", default="ANY"), - ), + ("owner_type", sgqlc.types.Arg(sgqlc.types.non_null(MetafieldOwnerType), graphql_name="ownerType", default=None)), + ("pinned_status", sgqlc.types.Arg(MetafieldDefinitionPinnedStatus, graphql_name="pinnedStatus", default="ANY")), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -16740,12 +19702,33 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - metafield_storefront_visibilities = sgqlc.types.Field( - sgqlc.types.non_null(MetafieldStorefrontVisibilityConnection), - graphql_name="metafieldStorefrontVisibilities", + metaobject = sgqlc.types.Field( + "Metaobject", + graphql_name="metaobject", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + metaobject_by_handle = sgqlc.types.Field( + "Metaobject", + graphql_name="metaobjectByHandle", + args=sgqlc.types.ArgDict( + (("handle", sgqlc.types.Arg(sgqlc.types.non_null(MetaobjectHandleInput), graphql_name="handle", default=None)),) + ), + ) + metaobject_definition = sgqlc.types.Field( + "MetaobjectDefinition", + graphql_name="metaobjectDefinition", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + metaobject_definition_by_type = sgqlc.types.Field( + "MetaobjectDefinition", + graphql_name="metaobjectDefinitionByType", + args=sgqlc.types.ArgDict((("type", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="type", default=None)),)), + ) + metaobject_definitions = sgqlc.types.Field( + sgqlc.types.non_null(MetaobjectDefinitionConnection), + graphql_name="metaobjectDefinitions", args=sgqlc.types.ArgDict( ( - ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -16754,10 +19737,21 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - metafield_storefront_visibility = sgqlc.types.Field( - "MetafieldStorefrontVisibility", - graphql_name="metafieldStorefrontVisibility", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + metaobjects = sgqlc.types.Field( + sgqlc.types.non_null(MetaobjectConnection), + graphql_name="metaobjects", + args=sgqlc.types.ArgDict( + ( + ("type", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="type", default=None)), + ("sort_key", sgqlc.types.Arg(String, graphql_name="sortKey", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), ) node = sgqlc.types.Field( Node, @@ -16771,11 +19765,7 @@ class QueryRoot(sgqlc.types.Type): ( ( "ids", - sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="ids", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="ids", default=None), ), ) ), @@ -16790,10 +19780,7 @@ class QueryRoot(sgqlc.types.Type): graphql_name="orderPaymentStatus", args=sgqlc.types.ArgDict( ( - ( - "payment_reference_id", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="paymentReferenceId", default=None), - ), + ("payment_reference_id", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="paymentReferenceId", default=None)), ("order_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="orderId", default=None)), ) ), @@ -16827,6 +19814,25 @@ class QueryRoot(sgqlc.types.Type): ) ), ) + payment_customization = sgqlc.types.Field( + "PaymentCustomization", + graphql_name="paymentCustomization", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + payment_customizations = sgqlc.types.Field( + sgqlc.types.non_null(PaymentCustomizationConnection), + graphql_name="paymentCustomizations", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) payment_terms_templates = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("PaymentTermsTemplate"))), graphql_name="paymentTermsTemplates", @@ -16844,7 +19850,6 @@ class QueryRoot(sgqlc.types.Type): graphql_name="priceLists", args=sgqlc.types.ArgDict( ( - ("match_rule", sgqlc.types.Arg(PriceListContext, graphql_name="matchRule", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -16854,11 +19859,6 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - price_rule = sgqlc.types.Field( - "PriceRule", - graphql_name="priceRule", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) price_rule_saved_searches = sgqlc.types.Field( sgqlc.types.non_null("SavedSearchConnection"), graphql_name="priceRuleSavedSearches", @@ -16872,35 +19872,32 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - price_rules = sgqlc.types.Field( - sgqlc.types.non_null(PriceRuleConnection), - graphql_name="priceRules", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ("sort_key", sgqlc.types.Arg(PriceRuleSortKeys, graphql_name="sortKey", default="ID")), - ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), - ("saved_search_id", sgqlc.types.Arg(ID, graphql_name="savedSearchId", default=None)), - ) - ), - ) primary_market = sgqlc.types.Field(sgqlc.types.non_null("Market"), graphql_name="primaryMarket") - private_metafield = sgqlc.types.Field( - "PrivateMetafield", - graphql_name="privateMetafield", + product = sgqlc.types.Field( + "Product", + graphql_name="product", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + product_by_handle = sgqlc.types.Field( + "Product", + graphql_name="productByHandle", + args=sgqlc.types.ArgDict((("handle", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="handle", default=None)),)), + ) + product_duplicate_job = sgqlc.types.Field( + sgqlc.types.non_null(ProductDuplicateJob), + graphql_name="productDuplicateJob", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + product_feed = sgqlc.types.Field( + "ProductFeed", + graphql_name="productFeed", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) - private_metafields = sgqlc.types.Field( - sgqlc.types.non_null(PrivateMetafieldConnection), - graphql_name="privateMetafields", + product_feeds = sgqlc.types.Field( + sgqlc.types.non_null(ProductFeedConnection), + graphql_name="productFeeds", args=sgqlc.types.ArgDict( ( - ("namespace", sgqlc.types.Arg(String, graphql_name="namespace", default=None)), - ("owner", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="owner", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -16909,16 +19906,6 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - product = sgqlc.types.Field( - "Product", - graphql_name="product", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), - ) - product_by_handle = sgqlc.types.Field( - "Product", - graphql_name="productByHandle", - args=sgqlc.types.ArgDict((("handle", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="handle", default=None)),)), - ) product_resource_feedback = sgqlc.types.Field( ProductResourceFeedback, graphql_name="productResourceFeedback", @@ -16977,16 +19964,46 @@ class QueryRoot(sgqlc.types.Type): public_api_versions = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ApiVersion))), graphql_name="publicApiVersions" ) - publication = sgqlc.types.Field( - "Publication", - graphql_name="publication", + publication = sgqlc.types.Field( + "Publication", + graphql_name="publication", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + publications = sgqlc.types.Field( + sgqlc.types.non_null(PublicationConnection), + graphql_name="publications", + args=sgqlc.types.ArgDict( + ( + ("catalog_type", sgqlc.types.Arg(CatalogType, graphql_name="catalogType", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + refund = sgqlc.types.Field( + "Refund", + graphql_name="refund", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + return_ = sgqlc.types.Field( + "Return", + graphql_name="return", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + returnable_fulfillment = sgqlc.types.Field( + "ReturnableFulfillment", + graphql_name="returnableFulfillment", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) - publications = sgqlc.types.Field( - sgqlc.types.non_null(PublicationConnection), - graphql_name="publications", + returnable_fulfillments = sgqlc.types.Field( + sgqlc.types.non_null("ReturnableFulfillmentConnection"), + graphql_name="returnableFulfillments", args=sgqlc.types.ArgDict( ( + ("order_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="orderId", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -16995,9 +20012,14 @@ class QueryRoot(sgqlc.types.Type): ) ), ) - refund = sgqlc.types.Field( - "Refund", - graphql_name="refund", + reverse_delivery = sgqlc.types.Field( + "ReverseDelivery", + graphql_name="reverseDelivery", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + reverse_fulfillment_order = sgqlc.types.Field( + "ReverseFulfillmentOrder", + graphql_name="reverseFulfillmentOrder", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) script_tag = sgqlc.types.Field( @@ -17068,6 +20090,7 @@ class QueryRoot(sgqlc.types.Type): ( ("search", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="search", default=None)), ("filter_query_name", sgqlc.types.Arg(String, graphql_name="filterQueryName", default=None)), + ("function_parameter_query_name", sgqlc.types.Arg(String, graphql_name="functionParameterQueryName", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -17110,17 +20133,42 @@ class QueryRoot(sgqlc.types.Type): ) ), ) + server_pixel = sgqlc.types.Field("ServerPixel", graphql_name="serverPixel") shop = sgqlc.types.Field(sgqlc.types.non_null("Shop"), graphql_name="shop") + shop_billing_preferences = sgqlc.types.Field(sgqlc.types.non_null("ShopBillingPreferences"), graphql_name="shopBillingPreferences") shop_locales = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopLocale"))), graphql_name="shopLocales", args=sgqlc.types.ArgDict((("published", sgqlc.types.Arg(Boolean, graphql_name="published", default=False)),)), ) + shopify_function = sgqlc.types.Field( + "ShopifyFunction", + graphql_name="shopifyFunction", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="id", default=None)),)), + ) + shopify_functions = sgqlc.types.Field( + sgqlc.types.non_null("ShopifyFunctionConnection"), + graphql_name="shopifyFunctions", + args=sgqlc.types.ArgDict( + ( + ("api_type", sgqlc.types.Arg(String, graphql_name="apiType", default=None)), + ("use_creation_ui", sgqlc.types.Arg(Boolean, graphql_name="useCreationUi", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) shopify_payments_account = sgqlc.types.Field("ShopifyPaymentsAccount", graphql_name="shopifyPaymentsAccount") + shopifyql_query = sgqlc.types.Field( + ShopifyqlResponse, + graphql_name="shopifyqlQuery", + args=sgqlc.types.ArgDict((("query", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="query", default=None)),)), + ) staff_member = sgqlc.types.Field( - "StaffMember", - graphql_name="staffMember", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)), + "StaffMember", graphql_name="staffMember", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)) ) standard_metafield_definition_templates = sgqlc.types.Field( sgqlc.types.non_null("StandardMetafieldDefinitionTemplateConnection"), @@ -17140,6 +20188,21 @@ class QueryRoot(sgqlc.types.Type): graphql_name="subscriptionBillingAttempt", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), ) + subscription_billing_attempts = sgqlc.types.Field( + sgqlc.types.non_null("SubscriptionBillingAttemptConnection"), + graphql_name="subscriptionBillingAttempts", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(SubscriptionBillingAttemptsSortKeys, graphql_name="sortKey", default="CREATED_AT")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) subscription_billing_cycle = sgqlc.types.Field( "SubscriptionBillingCycle", graphql_name="subscriptionBillingCycle", @@ -17147,11 +20210,7 @@ class QueryRoot(sgqlc.types.Type): ( ( "billing_cycle_input", - sgqlc.types.Arg( - sgqlc.types.non_null(SubscriptionBillingCycleInput), - graphql_name="billingCycleInput", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.non_null(SubscriptionBillingCycleInput), graphql_name="billingCycleInput", default=None), ), ) ), @@ -17165,17 +20224,13 @@ class QueryRoot(sgqlc.types.Type): ( "billing_cycles_date_range_selector", sgqlc.types.Arg( - SubscriptionBillingCyclesDateRangeSelector, - graphql_name="billingCyclesDateRangeSelector", - default=None, + SubscriptionBillingCyclesDateRangeSelector, graphql_name="billingCyclesDateRangeSelector", default=None ), ), ( "billing_cycles_index_range_selector", sgqlc.types.Arg( - SubscriptionBillingCyclesIndexRangeSelector, - graphql_name="billingCyclesIndexRangeSelector", - default=None, + SubscriptionBillingCyclesIndexRangeSelector, graphql_name="billingCyclesIndexRangeSelector", default=None ), ), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -17183,10 +20238,7 @@ class QueryRoot(sgqlc.types.Type): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX"), - ), + ("sort_key", sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX")), ) ), ) @@ -17205,6 +20257,7 @@ class QueryRoot(sgqlc.types.Type): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), ) ), ) @@ -17257,9 +20310,7 @@ class QueryRoot(sgqlc.types.Type): ( "resource_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="resourceIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="resourceIds", default=None ), ), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -17310,9 +20361,7 @@ class QueryRoot(sgqlc.types.Type): ), ) web_pixel = sgqlc.types.Field( - "WebPixel", - graphql_name="webPixel", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + "WebPixel", graphql_name="webPixel", args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(ID, graphql_name="id", default=None)),)) ) webhook_subscription = sgqlc.types.Field( "WebhookSubscription", @@ -17329,19 +20378,14 @@ class QueryRoot(sgqlc.types.Type): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(WebhookSubscriptionSortKeys, graphql_name="sortKey", default="CREATED_AT"), - ), + ("sort_key", sgqlc.types.Arg(WebhookSubscriptionSortKeys, graphql_name="sortKey", default="CREATED_AT")), ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), ("callback_url", sgqlc.types.Arg(URL, graphql_name="callbackUrl", default=None)), ("format", sgqlc.types.Arg(WebhookSubscriptionFormat, graphql_name="format", default=None)), ( "topics", sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(WebhookSubscriptionTopic)), - graphql_name="topics", - default=None, + sgqlc.types.list_of(sgqlc.types.non_null(WebhookSubscriptionTopic)), graphql_name="topics", default=None ), ), ) @@ -17349,147 +20393,454 @@ class QueryRoot(sgqlc.types.Type): ) -class RefundCreatePayload(sgqlc.types.Type): +class RefundConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("RefundEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Refund"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class RefundCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("order", "refund", "user_errors") + order = sgqlc.types.Field("Order", graphql_name="order") + refund = sgqlc.types.Field("Refund", graphql_name="refund") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + + +class RefundDuty(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("amount_set", "original_duty") + amount_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="amountSet") + original_duty = sgqlc.types.Field("Duty", graphql_name="originalDuty") + + +class RefundEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("Refund"), graphql_name="node") + + +class RefundLineItem(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("line_item", "location", "price_set", "quantity", "restock_type", "restocked", "subtotal_set", "total_tax_set") + line_item = sgqlc.types.Field(sgqlc.types.non_null("LineItem"), graphql_name="lineItem") + location = sgqlc.types.Field("Location", graphql_name="location") + price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="priceSet") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + restock_type = sgqlc.types.Field(sgqlc.types.non_null(RefundLineItemRestockType), graphql_name="restockType") + restocked = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="restocked") + subtotal_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="subtotalSet") + total_tax_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalTaxSet") + + +class RefundLineItemConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("RefundLineItemEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(RefundLineItem))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class RefundLineItemEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(RefundLineItem), graphql_name="node") + + +class ResourceAlert(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("actions", "content", "dismissible_handle", "icon", "severity", "title") + actions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourceAlertAction"))), graphql_name="actions" + ) + content = sgqlc.types.Field(sgqlc.types.non_null(HTML), graphql_name="content") + dismissible_handle = sgqlc.types.Field(String, graphql_name="dismissibleHandle") + icon = sgqlc.types.Field(ResourceAlertIcon, graphql_name="icon") + severity = sgqlc.types.Field(sgqlc.types.non_null(ResourceAlertSeverity), graphql_name="severity") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + +class ResourceAlertAction(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("primary", "show", "title", "url") + primary = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="primary") + show = sgqlc.types.Field(String, graphql_name="show") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") + + +class ResourceFeedback(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("details", "summary") + details = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppFeedback))), graphql_name="details") + summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") + + +class ResourceLimit(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("available", "quantity_available", "quantity_limit", "quantity_used") + available = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="available") + quantity_available = sgqlc.types.Field(Int, graphql_name="quantityAvailable") + quantity_limit = sgqlc.types.Field(Int, graphql_name="quantityLimit") + quantity_used = sgqlc.types.Field(Int, graphql_name="quantityUsed") + + +class ResourcePublication(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("is_published", "publication", "publish_date", "publishable") + is_published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isPublished") + publication = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="publication") + publish_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="publishDate") + publishable = sgqlc.types.Field(sgqlc.types.non_null(Publishable), graphql_name="publishable") + + +class ResourcePublicationConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourcePublicationEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourcePublication))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ResourcePublicationEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(ResourcePublication), graphql_name="node") + + +class ResourcePublicationV2(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("is_published", "publication", "publish_date", "publishable") + is_published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isPublished") + publication = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="publication") + publish_date = sgqlc.types.Field(DateTime, graphql_name="publishDate") + publishable = sgqlc.types.Field(sgqlc.types.non_null(Publishable), graphql_name="publishable") + + +class ResourcePublicationV2Connection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourcePublicationV2Edge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourcePublicationV2))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ResourcePublicationV2Edge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(ResourcePublicationV2), graphql_name="node") + + +class ReturnApproveRequestPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnCancelPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnClosePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Return"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ReturnCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnDecline(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("note", "reason") + note = sgqlc.types.Field(String, graphql_name="note") + reason = sgqlc.types.Field(sgqlc.types.non_null(ReturnDeclineReason), graphql_name="reason") + + +class ReturnDeclineRequestPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("Return"), graphql_name="node") + + +class ReturnLineItemConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnLineItemEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnLineItem"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ReturnLineItemEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ReturnLineItem"), graphql_name="node") + + +class ReturnRefundPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("refund", "user_errors") + refund = sgqlc.types.Field("Refund", graphql_name="refund") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnReopenPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnRequestPayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("return_", "user_errors") + return_ = sgqlc.types.Field("Return", graphql_name="return") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReturnableFulfillmentConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema - __field_names__ = ("order", "refund", "user_errors") - order = sgqlc.types.Field("Order", graphql_name="order") - refund = sgqlc.types.Field("Refund", graphql_name="refund") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnableFulfillmentEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnableFulfillment"))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class RefundDuty(sgqlc.types.Type): +class ReturnableFulfillmentEdge(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("amount_set", "original_duty") - amount_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="amountSet") - original_duty = sgqlc.types.Field("Duty", graphql_name="originalDuty") + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ReturnableFulfillment"), graphql_name="node") -class RefundLineItem(sgqlc.types.Type): +class ReturnableFulfillmentLineItem(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "line_item", - "location", - "price_set", - "quantity", - "restock_type", - "restocked", - "subtotal_set", - "total_tax_set", - ) - line_item = sgqlc.types.Field(sgqlc.types.non_null("LineItem"), graphql_name="lineItem") - location = sgqlc.types.Field("Location", graphql_name="location") - price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="priceSet") + __field_names__ = ("fulfillment_line_item", "quantity") + fulfillment_line_item = sgqlc.types.Field(sgqlc.types.non_null("FulfillmentLineItem"), graphql_name="fulfillmentLineItem") quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") - restock_type = sgqlc.types.Field(sgqlc.types.non_null(RefundLineItemRestockType), graphql_name="restockType") - restocked = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="restocked") - subtotal_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="subtotalSet") - total_tax_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalTaxSet") -class RefundLineItemConnection(sgqlc.types.relay.Connection): +class ReturnableFulfillmentLineItemConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("RefundLineItemEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(RefundLineItem))), graphql_name="nodes") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnableFulfillmentLineItemEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ReturnableFulfillmentLineItem))), graphql_name="nodes" + ) page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class RefundLineItemEdge(sgqlc.types.Type): +class ReturnableFulfillmentLineItemEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(RefundLineItem), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null(ReturnableFulfillmentLineItem), graphql_name="node") -class ResourceAlert(sgqlc.types.Type): +class ReverseDeliveryConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema - __field_names__ = ("actions", "content", "dismissible_handle", "icon", "severity", "title") - actions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourceAlertAction"))), graphql_name="actions" - ) - content = sgqlc.types.Field(sgqlc.types.non_null(HTML), graphql_name="content") - dismissible_handle = sgqlc.types.Field(String, graphql_name="dismissibleHandle") - icon = sgqlc.types.Field(ResourceAlertIcon, graphql_name="icon") - severity = sgqlc.types.Field(sgqlc.types.non_null(ResourceAlertSeverity), graphql_name="severity") - title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseDeliveryEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseDelivery"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class ResourceAlertAction(sgqlc.types.Type): +class ReverseDeliveryCreateWithShippingPayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("primary", "show", "title", "url") - primary = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="primary") - show = sgqlc.types.Field(String, graphql_name="show") - title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") - url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") + __field_names__ = ("reverse_delivery", "user_errors") + reverse_delivery = sgqlc.types.Field("ReverseDelivery", graphql_name="reverseDelivery") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) -class ResourceFeedback(sgqlc.types.Type): +class ReverseDeliveryDisposePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("details", "summary") - details = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppFeedback))), graphql_name="details") - summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") + __field_names__ = ("reverse_delivery_line_items", "user_errors") + reverse_delivery_line_items = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("ReverseDeliveryLineItem")), graphql_name="reverseDeliveryLineItems" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) -class ResourceLimit(sgqlc.types.Type): +class ReverseDeliveryEdge(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("available", "quantity_available", "quantity_limit", "quantity_used") - available = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="available") - quantity_available = sgqlc.types.Field(Int, graphql_name="quantityAvailable") - quantity_limit = sgqlc.types.Field(Int, graphql_name="quantityLimit") - quantity_used = sgqlc.types.Field(Int, graphql_name="quantityUsed") + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ReverseDelivery"), graphql_name="node") -class ResourcePublication(sgqlc.types.Type): +class ReverseDeliveryLabelV2(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("is_published", "publication", "publish_date", "publishable") - is_published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isPublished") - publication = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="publication") - publish_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="publishDate") - publishable = sgqlc.types.Field(sgqlc.types.non_null(Publishable), graphql_name="publishable") + __field_names__ = ("created_at", "public_file_url", "updated_at") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + public_file_url = sgqlc.types.Field(URL, graphql_name="publicFileUrl") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") -class ResourcePublicationConnection(sgqlc.types.relay.Connection): +class ReverseDeliveryLineItemConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourcePublicationEdge"))), graphql_name="edges" + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseDeliveryLineItemEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseDeliveryLineItem"))), graphql_name="nodes" ) - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourcePublication))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class ResourcePublicationEdge(sgqlc.types.Type): +class ReverseDeliveryLineItemEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(ResourcePublication), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null("ReverseDeliveryLineItem"), graphql_name="node") -class ResourcePublicationV2(sgqlc.types.Type): +class ReverseDeliveryShippingDeliverable(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("is_published", "publication", "publish_date", "publishable") - is_published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isPublished") - publication = sgqlc.types.Field(sgqlc.types.non_null("Publication"), graphql_name="publication") - publish_date = sgqlc.types.Field(DateTime, graphql_name="publishDate") - publishable = sgqlc.types.Field(sgqlc.types.non_null(Publishable), graphql_name="publishable") + __field_names__ = ("label", "tracking") + label = sgqlc.types.Field(ReverseDeliveryLabelV2, graphql_name="label") + tracking = sgqlc.types.Field("ReverseDeliveryTrackingV2", graphql_name="tracking") -class ResourcePublicationV2Connection(sgqlc.types.relay.Connection): +class ReverseDeliveryShippingUpdatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("reverse_delivery", "user_errors") + reverse_delivery = sgqlc.types.Field("ReverseDelivery", graphql_name="reverseDelivery") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReverseDeliveryTrackingV2(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("carrier_name", "number", "url") + carrier_name = sgqlc.types.Field(String, graphql_name="carrierName") + number = sgqlc.types.Field(String, graphql_name="number") + url = sgqlc.types.Field(URL, graphql_name="url") + + +class ReverseFulfillmentOrderConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ResourcePublicationV2Edge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrderEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrder"))), graphql_name="nodes" ) - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ResourcePublicationV2))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class ResourcePublicationV2Edge(sgqlc.types.Type): +class ReverseFulfillmentOrderDisposePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("reverse_fulfillment_order_line_items", "user_errors") + reverse_fulfillment_order_line_items = sgqlc.types.Field( + sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrderLineItem")), graphql_name="reverseFulfillmentOrderLineItems" + ) + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReturnUserError"))), graphql_name="userErrors" + ) + + +class ReverseFulfillmentOrderEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(ResourcePublicationV2), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null("ReverseFulfillmentOrder"), graphql_name="node") + + +class ReverseFulfillmentOrderLineItemConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrderLineItemEdge"))), graphql_name="edges" + ) + nodes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrderLineItem"))), graphql_name="nodes" + ) + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ReverseFulfillmentOrderLineItemEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null("ReverseFulfillmentOrderLineItem"), graphql_name="node") + + +class ReverseFulfillmentOrderThirdPartyConfirmation(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("status",) + status = sgqlc.types.Field(sgqlc.types.non_null(ReverseFulfillmentOrderThirdPartyConfirmationStatus), graphql_name="status") + + +class RowCount(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("count", "exceeds_max") + count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="count") + exceeds_max = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="exceedsMax") class SEO(sgqlc.types.Type): @@ -17499,30 +20850,6 @@ class SEO(sgqlc.types.Type): title = sgqlc.types.Field(String, graphql_name="title") -class Sale(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ( - "action_type", - "id", - "line_type", - "quantity", - "taxes", - "total_amount", - "total_discount_amount_after_taxes", - "total_discount_amount_before_taxes", - "total_tax_amount", - ) - action_type = sgqlc.types.Field(sgqlc.types.non_null(SaleActionType), graphql_name="actionType") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - line_type = sgqlc.types.Field(sgqlc.types.non_null(SaleLineType), graphql_name="lineType") - quantity = sgqlc.types.Field(Int, graphql_name="quantity") - taxes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SaleTax"))), graphql_name="taxes") - total_amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalAmount") - total_discount_amount_after_taxes = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalDiscountAmountAfterTaxes") - total_discount_amount_before_taxes = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalDiscountAmountBeforeTaxes") - total_tax_amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalTaxAmount") - - class SaleConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -17546,29 +20873,6 @@ class SaleTax(sgqlc.types.Type): tax_line = sgqlc.types.Field(sgqlc.types.non_null("TaxLine"), graphql_name="taxLine") -class SalesAgreement(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("app", "happened_at", "id", "reason", "sales", "user") - app = sgqlc.types.Field("App", graphql_name="app") - happened_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="happenedAt") - id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") - reason = sgqlc.types.Field(sgqlc.types.non_null(OrderActionType), graphql_name="reason") - sales = sgqlc.types.Field( - sgqlc.types.non_null(SaleConnection), - graphql_name="sales", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - user = sgqlc.types.Field("StaffMember", graphql_name="user") - - class SalesAgreementConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") @@ -17668,8 +20972,7 @@ class SearchFilterOptions(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("product_availability",) product_availability = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FilterOption))), - graphql_name="productAvailability", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FilterOption))), graphql_name="productAvailability" ) @@ -17697,34 +21000,6 @@ class SearchResultEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null(SearchResult), graphql_name="node") -class SegmentAssociationFilterValue(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("localized_name", "query_name") - localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") - - -class SegmentAssociationFilterValueConnection(sgqlc.types.relay.Connection): - __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentAssociationFilterValueEdge"))), - graphql_name="edges", - ) - nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentAssociationFilterValue))), - graphql_name="nodes", - ) - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") - - -class SegmentAssociationFilterValueEdge(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(SegmentAssociationFilterValue), graphql_name="node") - - class SegmentAttributeStatistics(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("average", "sum") @@ -17733,101 +21008,42 @@ class SegmentAttributeStatistics(sgqlc.types.Type): class SegmentConnection(sgqlc.types.relay.Connection): - __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentEdge"))), graphql_name="edges") - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Segment"))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") - - -class SegmentCreatePayload(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("segment", "user_errors") - segment = sgqlc.types.Field("Segment", graphql_name="segment") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") - - -class SegmentDeletePayload(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("deleted_segment_id", "user_errors") - deleted_segment_id = sgqlc.types.Field(ID, graphql_name="deletedSegmentId") - user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") - - -class SegmentEdge(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null("Segment"), graphql_name="node") - - -class SegmentEnumFilterValue(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("localized_name", "query_name") - localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") - - -class SegmentEnumFilterValueConnection(sgqlc.types.relay.Connection): - __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentEnumFilterValueEdge"))), - graphql_name="edges", - ) - nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentEnumFilterValue))), graphql_name="nodes") - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") - - -class SegmentEnumFilterValueEdge(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(SegmentEnumFilterValue), graphql_name="node") - - -class SegmentEventFilterParameter(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("localized_description", "localized_name", "optional", "parameter_type", "query_name") - localized_description = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedDescription") - localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - optional = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="optional") - parameter_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="parameterType") - query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Segment"))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") -class SegmentEventFilterValue(sgqlc.types.Type): +class SegmentCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("localized_name", "query_name") - localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") + __field_names__ = ("segment", "user_errors") + segment = sgqlc.types.Field("Segment", graphql_name="segment") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") -class SegmentEventFilterValueConnection(sgqlc.types.relay.Connection): +class SegmentDeletePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentEventFilterValueEdge"))), - graphql_name="edges", - ) - nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentEventFilterValue))), graphql_name="nodes" - ) - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + __field_names__ = ("deleted_segment_id", "user_errors") + deleted_segment_id = sgqlc.types.Field(ID, graphql_name="deletedSegmentId") + user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") -class SegmentEventFilterValueEdge(sgqlc.types.Type): +class SegmentEdge(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("cursor", "node") cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(SegmentEventFilterValue), graphql_name="node") + node = sgqlc.types.Field(sgqlc.types.non_null("Segment"), graphql_name="node") -class SegmentFilter(sgqlc.types.Interface): +class SegmentEventFilterParameter(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("localized_name", "multi_value", "query_name") + __field_names__ = ("accepts_multiple_values", "localized_description", "localized_name", "optional", "parameter_type", "query_name") + accepts_multiple_values = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="acceptsMultipleValues") + localized_description = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedDescription") localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - multi_value = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="multiValue") + optional = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="optional") + parameter_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="parameterType") query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") @@ -17886,47 +21102,14 @@ class SegmentMigrationEdge(sgqlc.types.Type): class SegmentStatistics(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("attribute_statistics", "total_count") + __field_names__ = ("attribute_statistics",) attribute_statistics = sgqlc.types.Field( sgqlc.types.non_null(SegmentAttributeStatistics), graphql_name="attributeStatistics", args=sgqlc.types.ArgDict( - ( - ( - "attribute_name", - sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="attributeName", default=None), - ), - ) + (("attribute_name", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="attributeName", default=None)),) ), ) - total_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="totalCount") - - -class SegmentStringFilterValue(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("localized_name", "query_name") - localized_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="localizedName") - query_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="queryName") - - -class SegmentStringFilterValueConnection(sgqlc.types.relay.Connection): - __schema__ = shopify_schema - __field_names__ = ("edges", "nodes", "page_info") - edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SegmentStringFilterValueEdge"))), - graphql_name="edges", - ) - nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentStringFilterValue))), graphql_name="nodes" - ) - page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") - - -class SegmentStringFilterValueEdge(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ("cursor", "node") - cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") - node = sgqlc.types.Field(sgqlc.types.non_null(SegmentStringFilterValue), graphql_name="node") class SegmentUpdatePayload(sgqlc.types.Type): @@ -18020,14 +21203,7 @@ class SellingPlanFixedBillingPolicy(sgqlc.types.Type): class SellingPlanFixedDeliveryPolicy(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "anchors", - "cutoff", - "fulfillment_exact_time", - "fulfillment_trigger", - "intent", - "pre_anchor_behavior", - ) + __field_names__ = ("anchors", "cutoff", "fulfillment_exact_time", "fulfillment_trigger", "intent", "pre_anchor_behavior") anchors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SellingPlanAnchor))), graphql_name="anchors") cutoff = sgqlc.types.Field(Int, graphql_name="cutoff") fulfillment_exact_time = sgqlc.types.Field(DateTime, graphql_name="fulfillmentExactTime") @@ -18043,8 +21219,7 @@ class SellingPlanGroupAddProductVariantsPayload(sgqlc.types.Type): __field_names__ = ("selling_plan_group", "user_errors") selling_plan_group = sgqlc.types.Field("SellingPlanGroup", graphql_name="sellingPlanGroup") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18053,8 +21228,7 @@ class SellingPlanGroupAddProductsPayload(sgqlc.types.Type): __field_names__ = ("selling_plan_group", "user_errors") selling_plan_group = sgqlc.types.Field("SellingPlanGroup", graphql_name="sellingPlanGroup") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18071,8 +21245,7 @@ class SellingPlanGroupCreatePayload(sgqlc.types.Type): __field_names__ = ("selling_plan_group", "user_errors") selling_plan_group = sgqlc.types.Field("SellingPlanGroup", graphql_name="sellingPlanGroup") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18081,8 +21254,7 @@ class SellingPlanGroupDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_selling_plan_group_id", "user_errors") deleted_selling_plan_group_id = sgqlc.types.Field(ID, graphql_name="deletedSellingPlanGroupId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18098,8 +21270,7 @@ class SellingPlanGroupRemoveProductVariantsPayload(sgqlc.types.Type): __field_names__ = ("removed_product_variant_ids", "user_errors") removed_product_variant_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="removedProductVariantIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18108,8 +21279,7 @@ class SellingPlanGroupRemoveProductsPayload(sgqlc.types.Type): __field_names__ = ("removed_product_ids", "user_errors") removed_product_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="removedProductIds") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18119,8 +21289,7 @@ class SellingPlanGroupUpdatePayload(sgqlc.types.Type): deleted_selling_plan_ids = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="deletedSellingPlanIds") selling_plan_group = sgqlc.types.Field("SellingPlanGroup", graphql_name="sellingPlanGroup") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanGroupUserError"))), graphql_name="userErrors" ) @@ -18130,13 +21299,6 @@ class SellingPlanInventoryPolicy(sgqlc.types.Type): reserve = sgqlc.types.Field(sgqlc.types.non_null(SellingPlanReserve), graphql_name="reserve") -class SellingPlanPricingPolicyBase(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("adjustment_type", "adjustment_value") - adjustment_type = sgqlc.types.Field(sgqlc.types.non_null(SellingPlanPricingPolicyAdjustmentType), graphql_name="adjustmentType") - adjustment_value = sgqlc.types.Field(sgqlc.types.non_null("SellingPlanPricingPolicyAdjustmentValue"), graphql_name="adjustmentValue") - - class SellingPlanPricingPolicyPercentageValue(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("percentage",) @@ -18168,6 +21330,24 @@ class SellingPlanRecurringDeliveryPolicy(sgqlc.types.Type): ) +class ServerPixelCreatePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("server_pixel", "user_errors") + server_pixel = sgqlc.types.Field("ServerPixel", graphql_name="serverPixel") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsServerPixelUserError"))), graphql_name="userErrors" + ) + + +class ServerPixelDeletePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("deleted_server_pixel_id", "user_errors") + deleted_server_pixel_id = sgqlc.types.Field(ID, graphql_name="deletedServerPixelId") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsServerPixelUserError"))), graphql_name="userErrors" + ) + + class ShippingLine(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( @@ -18191,8 +21371,7 @@ class ShippingLine(sgqlc.types.Type): custom = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="custom") delivery_category = sgqlc.types.Field(String, graphql_name="deliveryCategory") discount_allocations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), - graphql_name="discountAllocations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), graphql_name="discountAllocations" ) discounted_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedPriceSet") id = sgqlc.types.Field(ID, graphql_name="id") @@ -18276,11 +21455,18 @@ class ShopAlertAction(sgqlc.types.Type): url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="url") +class ShopBillingPreferences(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("currency",) + currency = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currency") + + class ShopFeatures(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ( "avalara_avatax", "branding", + "bundles", "captcha", "captcha_external_domains", "dynamic_remarketing", @@ -18303,6 +21489,7 @@ class ShopFeatures(sgqlc.types.Type): ) avalara_avatax = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="avalaraAvatax") branding = sgqlc.types.Field(sgqlc.types.non_null(ShopBranding), graphql_name="branding") + bundles = sgqlc.types.Field(sgqlc.types.non_null(BundlesFeature), graphql_name="bundles") captcha = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="captcha") captcha_external_domains = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="captchaExternalDomains") dynamic_remarketing = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="dynamicRemarketing") @@ -18317,8 +21504,7 @@ class ShopFeatures(sgqlc.types.Type): live_view = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="liveView") onboarding_visual = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="onboardingVisual") paypal_express_subscription_gateway_status = sgqlc.types.Field( - sgqlc.types.non_null(PaypalExpressSubscriptionsGatewayStatus), - graphql_name="paypalExpressSubscriptionGatewayStatus", + sgqlc.types.non_null(PaypalExpressSubscriptionsGatewayStatus), graphql_name="paypalExpressSubscriptionGatewayStatus" ) reports = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="reports") sells_subscriptions = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="sellsSubscriptions") @@ -18332,8 +21518,7 @@ class ShopLocale(sgqlc.types.Type): __field_names__ = ("locale", "market_web_presences", "name", "primary", "published") locale = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="locale") market_web_presences = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketWebPresence"))), - graphql_name="marketWebPresences", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MarketWebPresence"))), graphql_name="marketWebPresences" ) name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") primary = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="primary") @@ -18374,37 +21559,77 @@ class ShopPolicyUpdatePayload(sgqlc.types.Type): __field_names__ = ("shop_policy", "user_errors") shop_policy = sgqlc.types.Field("ShopPolicy", graphql_name="shopPolicy") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopPolicyUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopPolicyUserError"))), graphql_name="userErrors" ) -class ShopResourceLimits(sgqlc.types.Type): +class ShopResourceFeedbackCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "location_limit", - "max_product_options", - "max_product_variants", - "redirect_limit_reached", - "sku_resource_limits", + __field_names__ = ("feedback", "user_errors") + feedback = sgqlc.types.Field(AppFeedback, graphql_name="feedback") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopResourceFeedbackCreateUserError"))), graphql_name="userErrors" ) + + +class ShopResourceLimits(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("location_limit", "max_product_options", "max_product_variants", "redirect_limit_reached") location_limit = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="locationLimit") max_product_options = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="maxProductOptions") max_product_variants = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="maxProductVariants") redirect_limit_reached = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="redirectLimitReached") - sku_resource_limits = sgqlc.types.Field(sgqlc.types.non_null(ResourceLimit), graphql_name="skuResourceLimits") + + +class ShopifyFunction(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ( + "api_type", + "api_version", + "app", + "app_bridge", + "app_key", + "description", + "id", + "input_query", + "title", + "use_creation_ui", + ) + api_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="apiType") + api_version = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="apiVersion") + app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") + app_bridge = sgqlc.types.Field(sgqlc.types.non_null(FunctionsAppBridge), graphql_name="appBridge") + app_key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="appKey") + description = sgqlc.types.Field(String, graphql_name="description") + id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="id") + input_query = sgqlc.types.Field(String, graphql_name="inputQuery") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + use_creation_ui = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="useCreationUi") + + +class ShopifyFunctionConnection(sgqlc.types.relay.Connection): + __schema__ = shopify_schema + __field_names__ = ("edges", "nodes", "page_info") + edges = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyFunctionEdge"))), graphql_name="edges") + nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ShopifyFunction))), graphql_name="nodes") + page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") + + +class ShopifyFunctionEdge(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("cursor", "node") + cursor = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="cursor") + node = sgqlc.types.Field(sgqlc.types.non_null(ShopifyFunction), graphql_name="node") class ShopifyPaymentsBankAccountConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsBankAccountEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsBankAccountEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsBankAccount"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsBankAccount"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -18416,19 +21641,11 @@ class ShopifyPaymentsBankAccountEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("ShopifyPaymentsBankAccount"), graphql_name="node") -class ShopifyPaymentsChargeStatementDescriptor(sgqlc.types.Interface): - __schema__ = shopify_schema - __field_names__ = ("default", "prefix") - default = sgqlc.types.Field(String, graphql_name="default") - prefix = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="prefix") - - class ShopifyPaymentsDisputeConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsDisputeEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsDisputeEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsDispute"))), graphql_name="nodes" @@ -18474,8 +21691,7 @@ class ShopifyPaymentsPayoutConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsPayoutEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsPayoutEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsPayout"))), graphql_name="nodes" @@ -18578,8 +21794,7 @@ class StagedMediaUploadTarget(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("parameters", "resource_url", "url") parameters = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StagedUploadParameter"))), - graphql_name="parameters", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StagedUploadParameter"))), graphql_name="parameters" ) resource_url = sgqlc.types.Field(URL, graphql_name="resourceUrl") url = sgqlc.types.Field(URL, graphql_name="url") @@ -18640,12 +21855,10 @@ class StandardMetafieldDefinitionTemplateConnection(sgqlc.types.relay.Connection __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StandardMetafieldDefinitionTemplateEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StandardMetafieldDefinitionTemplateEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StandardMetafieldDefinitionTemplate"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StandardMetafieldDefinitionTemplate"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -18657,6 +21870,15 @@ class StandardMetafieldDefinitionTemplateEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("StandardMetafieldDefinitionTemplate"), graphql_name="node") +class StandardMetaobjectDefinitionEnablePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("metaobject_definition", "user_errors") + metaobject_definition = sgqlc.types.Field("MetaobjectDefinition", graphql_name="metaobjectDefinition") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("MetaobjectUserError"))), graphql_name="userErrors" + ) + + class StandardizedProductType(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("product_taxonomy_node",) @@ -18667,8 +21889,7 @@ class StorefrontAccessTokenConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StorefrontAccessTokenEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StorefrontAccessTokenEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("StorefrontAccessToken"))), graphql_name="nodes" @@ -18724,12 +21945,10 @@ class SubscriptionBillingAttemptConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingAttemptEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingAttemptEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingAttempt"))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingAttempt"))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -18739,8 +21958,7 @@ class SubscriptionBillingAttemptCreatePayload(sgqlc.types.Type): __field_names__ = ("subscription_billing_attempt", "user_errors") subscription_billing_attempt = sgqlc.types.Field("SubscriptionBillingAttempt", graphql_name="subscriptionBillingAttempt") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BillingAttemptUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("BillingAttemptUserError"))), graphql_name="userErrors" ) @@ -18793,8 +22011,7 @@ class SubscriptionBillingCycleConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionBillingCycle))), graphql_name="nodes" @@ -18807,8 +22024,7 @@ class SubscriptionBillingCycleContractDraftCommitPayload(sgqlc.types.Type): __field_names__ = ("contract", "user_errors") contract = sgqlc.types.Field("SubscriptionBillingCycleEditedContract", graphql_name="contract") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -18817,8 +22033,7 @@ class SubscriptionBillingCycleContractDraftConcatenatePayload(sgqlc.types.Type): __field_names__ = ("draft", "user_errors") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -18827,8 +22042,7 @@ class SubscriptionBillingCycleContractEditPayload(sgqlc.types.Type): __field_names__ = ("draft", "user_errors") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -18844,8 +22058,7 @@ class SubscriptionBillingCycleEditDeletePayload(sgqlc.types.Type): __field_names__ = ("billing_cycles", "user_errors") billing_cycles = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionBillingCycle)), graphql_name="billingCycles") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), graphql_name="userErrors" ) @@ -18854,8 +22067,7 @@ class SubscriptionBillingCycleEditsDeletePayload(sgqlc.types.Type): __field_names__ = ("billing_cycles", "user_errors") billing_cycles = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionBillingCycle)), graphql_name="billingCycles") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), graphql_name="userErrors" ) @@ -18864,8 +22076,7 @@ class SubscriptionBillingCycleScheduleEditPayload(sgqlc.types.Type): __field_names__ = ("billing_cycle", "user_errors") billing_cycle = sgqlc.types.Field(SubscriptionBillingCycle, graphql_name="billingCycle") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionBillingCycleUserError"))), graphql_name="userErrors" ) @@ -18879,88 +22090,20 @@ class SubscriptionBillingPolicy(sgqlc.types.Type): min_cycles = sgqlc.types.Field(Int, graphql_name="minCycles") -class SubscriptionContractBase(sgqlc.types.Interface): +class SubscriptionContractAtomicCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "app", - "app_admin_url", - "currency_code", - "custom_attributes", - "customer", - "customer_payment_method", - "delivery_method", - "delivery_price", - "discounts", - "line_count", - "lines", - "note", - "orders", - "updated_at", - ) - app = sgqlc.types.Field("App", graphql_name="app") - app_admin_url = sgqlc.types.Field(URL, graphql_name="appAdminUrl") - currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") - custom_attributes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" - ) - customer = sgqlc.types.Field("Customer", graphql_name="customer") - customer_payment_method = sgqlc.types.Field( - "CustomerPaymentMethod", - graphql_name="customerPaymentMethod", - args=sgqlc.types.ArgDict((("show_revoked", sgqlc.types.Arg(Boolean, graphql_name="showRevoked", default=False)),)), - ) - delivery_method = sgqlc.types.Field("SubscriptionDeliveryMethod", graphql_name="deliveryMethod") - delivery_price = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="deliveryPrice") - discounts = sgqlc.types.Field( - sgqlc.types.non_null("SubscriptionManualDiscountConnection"), - graphql_name="discounts", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - line_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="lineCount") - lines = sgqlc.types.Field( - sgqlc.types.non_null("SubscriptionLineConnection"), - graphql_name="lines", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), - ) - note = sgqlc.types.Field(String, graphql_name="note") - orders = sgqlc.types.Field( - sgqlc.types.non_null(OrderConnection), - graphql_name="orders", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ) - ), + __field_names__ = ("contract", "user_errors") + contract = sgqlc.types.Field("SubscriptionContract", graphql_name="contract") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) - updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") class SubscriptionContractConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionContractEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionContractEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionContract"))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -18971,8 +22114,7 @@ class SubscriptionContractCreatePayload(sgqlc.types.Type): __field_names__ = ("draft", "user_errors") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -18983,13 +22125,22 @@ class SubscriptionContractEdge(sgqlc.types.Type): node = sgqlc.types.Field(sgqlc.types.non_null("SubscriptionContract"), graphql_name="node") +class SubscriptionContractProductChangePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("contract", "line_updated", "user_errors") + contract = sgqlc.types.Field("SubscriptionContract", graphql_name="contract") + line_updated = sgqlc.types.Field("SubscriptionLine", graphql_name="lineUpdated") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" + ) + + class SubscriptionContractSetNextBillingDatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("contract", "user_errors") contract = sgqlc.types.Field("SubscriptionContract", graphql_name="contract") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionContractUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionContractUserError"))), graphql_name="userErrors" ) @@ -18998,8 +22149,7 @@ class SubscriptionContractUpdatePayload(sgqlc.types.Type): __field_names__ = ("draft", "user_errors") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19057,8 +22207,7 @@ class SubscriptionDeliveryMethodShipping(sgqlc.types.Type): class SubscriptionDeliveryMethodShippingOption(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("carrier_service", "code", "description", "presentment_title", "title") - carrier_service = sgqlc.types.Field("DeliveryCarrierService", graphql_name="carrierService") + __field_names__ = ("code", "description", "presentment_title", "title") code = sgqlc.types.Field(String, graphql_name="code") description = sgqlc.types.Field(String, graphql_name="description") presentment_title = sgqlc.types.Field(String, graphql_name="presentmentTitle") @@ -19075,8 +22224,7 @@ class SubscriptionDeliveryOptionResultSuccess(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("delivery_options",) delivery_options = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDeliveryOption"))), - graphql_name="deliveryOptions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDeliveryOption"))), graphql_name="deliveryOptions" ) @@ -19099,8 +22247,7 @@ class SubscriptionDiscountConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDiscountEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDiscountEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDiscount"))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -19150,8 +22297,7 @@ class SubscriptionDraftCommitPayload(sgqlc.types.Type): __field_names__ = ("contract", "user_errors") contract = sgqlc.types.Field("SubscriptionContract", graphql_name="contract") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19161,8 +22307,7 @@ class SubscriptionDraftDiscountAddPayload(sgqlc.types.Type): discount_added = sgqlc.types.Field("SubscriptionManualDiscount", graphql_name="discountAdded") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19172,8 +22317,7 @@ class SubscriptionDraftDiscountCodeApplyPayload(sgqlc.types.Type): applied_discount = sgqlc.types.Field(SubscriptionAppliedCodeDiscount, graphql_name="appliedDiscount") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19183,8 +22327,7 @@ class SubscriptionDraftDiscountRemovePayload(sgqlc.types.Type): discount_removed = sgqlc.types.Field("SubscriptionDiscount", graphql_name="discountRemoved") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19194,8 +22337,7 @@ class SubscriptionDraftDiscountUpdatePayload(sgqlc.types.Type): discount_updated = sgqlc.types.Field("SubscriptionManualDiscount", graphql_name="discountUpdated") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19205,8 +22347,7 @@ class SubscriptionDraftFreeShippingDiscountAddPayload(sgqlc.types.Type): discount_added = sgqlc.types.Field("SubscriptionManualDiscount", graphql_name="discountAdded") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19216,8 +22357,7 @@ class SubscriptionDraftFreeShippingDiscountUpdatePayload(sgqlc.types.Type): discount_updated = sgqlc.types.Field("SubscriptionManualDiscount", graphql_name="discountUpdated") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19227,8 +22367,7 @@ class SubscriptionDraftLineAddPayload(sgqlc.types.Type): draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") line_added = sgqlc.types.Field("SubscriptionLine", graphql_name="lineAdded") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19241,8 +22380,7 @@ class SubscriptionDraftLineRemovePayload(sgqlc.types.Type): draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") line_removed = sgqlc.types.Field("SubscriptionLine", graphql_name="lineRemoved") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19252,8 +22390,7 @@ class SubscriptionDraftLineUpdatePayload(sgqlc.types.Type): draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") line_updated = sgqlc.types.Field("SubscriptionLine", graphql_name="lineUpdated") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19262,8 +22399,7 @@ class SubscriptionDraftUpdatePayload(sgqlc.types.Type): __field_names__ = ("draft", "user_errors") draft = sgqlc.types.Field("SubscriptionDraft", graphql_name="draft") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionDraftUserError"))), graphql_name="userErrors" ) @@ -19293,8 +22429,7 @@ class SubscriptionLine(sgqlc.types.Type): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" ) discount_allocations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionDiscountAllocation))), - graphql_name="discountAllocations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionDiscountAllocation))), graphql_name="discountAllocations" ) id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") line_discounted_price = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="lineDiscountedPrice") @@ -19398,12 +22533,10 @@ class SubscriptionManualDiscountConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionManualDiscountEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SubscriptionManualDiscountEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionManualDiscount))), - graphql_name="nodes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionManualDiscount))), graphql_name="nodes" ) page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -19417,16 +22550,7 @@ class SubscriptionManualDiscountEdge(sgqlc.types.Type): class SubscriptionPickupOption(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ( - "code", - "description", - "location", - "phone_required", - "pickup_time", - "presentment_title", - "price", - "title", - ) + __field_names__ = ("code", "description", "location", "phone_required", "pickup_time", "presentment_title", "price", "title") code = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="code") description = sgqlc.types.Field(String, graphql_name="description") location = sgqlc.types.Field(sgqlc.types.non_null("Location"), graphql_name="location") @@ -19442,23 +22566,13 @@ class SubscriptionPricingPolicy(sgqlc.types.Type): __field_names__ = ("base_price", "cycle_discounts") base_price = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="basePrice") cycle_discounts = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionCyclePriceAdjustment))), - graphql_name="cycleDiscounts", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionCyclePriceAdjustment))), graphql_name="cycleDiscounts" ) class SubscriptionShippingOption(sgqlc.types.Type): - __schema__ = shopify_schema - __field_names__ = ( - "carrier_service", - "code", - "description", - "phone_required", - "presentment_title", - "price", - "title", - ) - carrier_service = sgqlc.types.Field("DeliveryCarrierService", graphql_name="carrierService") + __schema__ = shopify_schema + __field_names__ = ("code", "description", "phone_required", "presentment_title", "price", "title") code = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="code") description = sgqlc.types.Field(String, graphql_name="description") phone_required = sgqlc.types.Field(Boolean, graphql_name="phoneRequired") @@ -19477,8 +22591,7 @@ class SubscriptionShippingOptionResultSuccess(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("shipping_options",) shipping_options = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionShippingOption))), - graphql_name="shippingOptions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SubscriptionShippingOption))), graphql_name="shippingOptions" ) @@ -19529,14 +22642,63 @@ class SuggestedRefund(sgqlc.types.Type): shipping = sgqlc.types.Field(sgqlc.types.non_null(ShippingRefund), graphql_name="shipping") subtotal_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="subtotalSet") suggested_transactions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SuggestedOrderTransaction))), - graphql_name="suggestedTransactions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SuggestedOrderTransaction))), graphql_name="suggestedTransactions" ) total_cart_discount_amount_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalCartDiscountAmountSet") total_duties_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalDutiesSet") total_tax_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalTaxSet") +class SuggestedReturnRefund(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ( + "amount", + "discounted_subtotal", + "maximum_refundable", + "refund_duties", + "shipping", + "subtotal", + "suggested_transactions", + "total_cart_discount_amount", + "total_duties", + "total_tax", + ) + amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="amount") + discounted_subtotal = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedSubtotal") + maximum_refundable = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="maximumRefundable") + refund_duties = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(RefundDuty))), graphql_name="refundDuties" + ) + shipping = sgqlc.types.Field(sgqlc.types.non_null(ShippingRefund), graphql_name="shipping") + subtotal = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="subtotal") + suggested_transactions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SuggestedOrderTransaction))), graphql_name="suggestedTransactions" + ) + total_cart_discount_amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalCartDiscountAmount") + total_duties = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalDuties") + total_tax = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalTax") + + +class TableData(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("columns", "row_data", "unformatted_data") + columns = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TableDataColumn"))), graphql_name="columns") + row_data = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))))), + graphql_name="rowData", + ) + unformatted_data = sgqlc.types.Field(sgqlc.types.non_null(JSON), graphql_name="unformattedData") + + +class TableDataColumn(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("compared_to", "data_type", "display_name", "name") + compared_to = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="comparedTo") + data_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="dataType") + display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + + class TagsAddPayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("node", "user_errors") @@ -19551,6 +22713,21 @@ class TagsRemovePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class TaxAppConfiguration(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("state",) + state = sgqlc.types.Field(sgqlc.types.non_null(TaxPartnerState), graphql_name="state") + + +class TaxAppConfigurePayload(sgqlc.types.Type): + __schema__ = shopify_schema + __field_names__ = ("tax_app_configuration", "user_errors") + tax_app_configuration = sgqlc.types.Field(TaxAppConfiguration, graphql_name="taxAppConfiguration") + user_errors = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TaxAppConfigureUserError"))), graphql_name="userErrors" + ) + + class TaxLine(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("channel_liable", "price_set", "rate", "rate_percentage", "title") @@ -19587,10 +22764,11 @@ class TenderTransactionEdge(sgqlc.types.Type): class TranslatableContent(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("digest", "key", "locale", "value") + __field_names__ = ("digest", "key", "locale", "type", "value") digest = sgqlc.types.Field(String, graphql_name="digest") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") locale = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="locale") + type = sgqlc.types.Field(sgqlc.types.non_null(LocalizableContentType), graphql_name="type") value = sgqlc.types.Field(String, graphql_name="value") @@ -19599,8 +22777,7 @@ class TranslatableResource(sgqlc.types.Type): __field_names__ = ("resource_id", "translatable_content", "translations") resource_id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="resourceId") translatable_content = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TranslatableContent))), - graphql_name="translatableContent", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TranslatableContent))), graphql_name="translatableContent" ) translations = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Translation"))), @@ -19619,8 +22796,7 @@ class TranslatableResourceConnection(sgqlc.types.relay.Connection): __schema__ = shopify_schema __field_names__ = ("edges", "nodes", "page_info") edges = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslatableResourceEdge"))), - graphql_name="edges", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslatableResourceEdge"))), graphql_name="edges" ) nodes = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TranslatableResource))), graphql_name="nodes") page_info = sgqlc.types.Field(sgqlc.types.non_null(PageInfo), graphql_name="pageInfo") @@ -19635,11 +22811,12 @@ class TranslatableResourceEdge(sgqlc.types.Type): class Translation(sgqlc.types.Type): __schema__ = shopify_schema - __field_names__ = ("key", "locale", "market", "outdated", "value") + __field_names__ = ("key", "locale", "market", "outdated", "updated_at", "value") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") locale = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="locale") market = sgqlc.types.Field("Market", graphql_name="market") outdated = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="outdated") + updated_at = sgqlc.types.Field(DateTime, graphql_name="updatedAt") value = sgqlc.types.Field(String, graphql_name="value") @@ -19648,8 +22825,7 @@ class TranslationsRegisterPayload(sgqlc.types.Type): __field_names__ = ("translations", "user_errors") translations = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(Translation)), graphql_name="translations") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), graphql_name="userErrors" ) @@ -19658,8 +22834,7 @@ class TranslationsRemovePayload(sgqlc.types.Type): __field_names__ = ("translations", "user_errors") translations = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(Translation)), graphql_name="translations") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("TranslationUserError"))), graphql_name="userErrors" ) @@ -19692,8 +22867,7 @@ class UrlRedirectBulkDeleteByIdsPayload(sgqlc.types.Type): __field_names__ = ("job", "user_errors") job = sgqlc.types.Field(Job, graphql_name="job") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectBulkDeleteByIdsUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectBulkDeleteByIdsUserError"))), graphql_name="userErrors" ) @@ -19712,8 +22886,7 @@ class UrlRedirectBulkDeleteBySearchPayload(sgqlc.types.Type): __field_names__ = ("job", "user_errors") job = sgqlc.types.Field(Job, graphql_name="job") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectBulkDeleteBySearchUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectBulkDeleteBySearchUserError"))), graphql_name="userErrors" ) @@ -19730,8 +22903,7 @@ class UrlRedirectCreatePayload(sgqlc.types.Type): __field_names__ = ("url_redirect", "user_errors") url_redirect = sgqlc.types.Field("UrlRedirect", graphql_name="urlRedirect") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), graphql_name="userErrors" ) @@ -19740,8 +22912,7 @@ class UrlRedirectDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_url_redirect_id", "user_errors") deleted_url_redirect_id = sgqlc.types.Field(ID, graphql_name="deletedUrlRedirectId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), graphql_name="userErrors" ) @@ -19757,8 +22928,7 @@ class UrlRedirectImportCreatePayload(sgqlc.types.Type): __field_names__ = ("url_redirect_import", "user_errors") url_redirect_import = sgqlc.types.Field("UrlRedirectImport", graphql_name="urlRedirectImport") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectImportUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectImportUserError"))), graphql_name="userErrors" ) @@ -19774,8 +22944,7 @@ class UrlRedirectImportSubmitPayload(sgqlc.types.Type): __field_names__ = ("job", "user_errors") job = sgqlc.types.Field(Job, graphql_name="job") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectImportUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectImportUserError"))), graphql_name="userErrors" ) @@ -19784,8 +22953,7 @@ class UrlRedirectUpdatePayload(sgqlc.types.Type): __field_names__ = ("url_redirect", "user_errors") url_redirect = sgqlc.types.Field("UrlRedirect", graphql_name="urlRedirect") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UrlRedirectUserError"))), graphql_name="userErrors" ) @@ -19832,8 +23000,7 @@ class WebPixelCreatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("user_errors", "web_pixel") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), graphql_name="userErrors" ) web_pixel = sgqlc.types.Field("WebPixel", graphql_name="webPixel") @@ -19843,8 +23010,7 @@ class WebPixelDeletePayload(sgqlc.types.Type): __field_names__ = ("deleted_web_pixel_id", "user_errors") deleted_web_pixel_id = sgqlc.types.Field(ID, graphql_name="deletedWebPixelId") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), graphql_name="userErrors" ) @@ -19852,8 +23018,7 @@ class WebPixelUpdatePayload(sgqlc.types.Type): __schema__ = shopify_schema __field_names__ = ("user_errors", "web_pixel") user_errors = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), - graphql_name="userErrors", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ErrorsWebPixelUserError"))), graphql_name="userErrors" ) web_pixel = sgqlc.types.Field("WebPixel", graphql_name="webPixel") @@ -19943,6 +23108,123 @@ class deliveryProfileUpdatePayload(sgqlc.types.Type): user_errors = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("UserError"))), graphql_name="userErrors") +class AbandonedCheckout(sgqlc.types.Type, Navigable, Node): + __schema__ = shopify_schema + __field_names__ = ("abandoned_checkout_url", "line_items_quantity", "total_price_set") + abandoned_checkout_url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="abandonedCheckoutUrl") + line_items_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="lineItemsQuantity") + total_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalPriceSet") + + +class Abandonment(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "abandoned_checkout_payload", + "abandonment_type", + "app", + "cart_url", + "created_at", + "customer", + "customer_has_no_order_since_abandonment", + "days_since_last_abandonment_email", + "email_sent_at", + "email_state", + "hours_since_last_abandoned_checkout", + "inventory_available", + "is_from_online_store", + "is_from_shop_app", + "is_from_shop_pay", + "is_most_significant_abandonment", + "last_browse_abandonment_date", + "last_cart_abandonment_date", + "last_checkout_abandonment_date", + "most_recent_step", + "products_added_to_cart", + "products_viewed", + "visit_started_at", + ) + abandoned_checkout_payload = sgqlc.types.Field(AbandonedCheckout, graphql_name="abandonedCheckoutPayload") + abandonment_type = sgqlc.types.Field(sgqlc.types.non_null(AbandonmentAbandonmentType), graphql_name="abandonmentType") + app = sgqlc.types.Field(sgqlc.types.non_null("App"), graphql_name="app") + cart_url = sgqlc.types.Field(URL, graphql_name="cartUrl") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + customer = sgqlc.types.Field(sgqlc.types.non_null("Customer"), graphql_name="customer") + customer_has_no_order_since_abandonment = sgqlc.types.Field( + sgqlc.types.non_null(Boolean), graphql_name="customerHasNoOrderSinceAbandonment" + ) + days_since_last_abandonment_email = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="daysSinceLastAbandonmentEmail") + email_sent_at = sgqlc.types.Field(DateTime, graphql_name="emailSentAt") + email_state = sgqlc.types.Field(AbandonmentEmailState, graphql_name="emailState") + hours_since_last_abandoned_checkout = sgqlc.types.Field(Float, graphql_name="hoursSinceLastAbandonedCheckout") + inventory_available = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="inventoryAvailable") + is_from_online_store = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isFromOnlineStore") + is_from_shop_app = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isFromShopApp") + is_from_shop_pay = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isFromShopPay") + is_most_significant_abandonment = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isMostSignificantAbandonment") + last_browse_abandonment_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="lastBrowseAbandonmentDate") + last_cart_abandonment_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="lastCartAbandonmentDate") + last_checkout_abandonment_date = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="lastCheckoutAbandonmentDate") + most_recent_step = sgqlc.types.Field(sgqlc.types.non_null(AbandonmentAbandonmentType), graphql_name="mostRecentStep") + products_added_to_cart = sgqlc.types.Field( + sgqlc.types.non_null(CustomerVisitProductInfoConnection), + graphql_name="productsAddedToCart", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + products_viewed = sgqlc.types.Field( + sgqlc.types.non_null(CustomerVisitProductInfoConnection), + graphql_name="productsViewed", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + visit_started_at = sgqlc.types.Field(DateTime, graphql_name="visitStartedAt") + + +class AbandonmentEmailStateUpdateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(AbandonmentEmailStateUpdateUserErrorCode, graphql_name="code") + + +class AbandonmentUpdateActivitiesDeliveryStatusesUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(AbandonmentUpdateActivitiesDeliveryStatusesUserErrorCode, graphql_name="code") + + +class AddAllProductsOperation(sgqlc.types.Type, Node, ResourceOperation): + __schema__ = shopify_schema + __field_names__ = () + + +class AdditionalFee(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("name", "price", "tax_lines") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + price = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="price") + tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TaxLine))), graphql_name="taxLines") + + +class AdditionalFeeSale(sgqlc.types.Type, Sale): + __schema__ = shopify_schema + __field_names__ = ("additional_fee",) + additional_fee = sgqlc.types.Field(sgqlc.types.non_null("SaleAdditionalFee"), graphql_name="additionalFee") + + class AdjustmentSale(sgqlc.types.Type, Sale): __schema__ = shopify_schema __field_names__ = () @@ -19985,8 +23267,7 @@ class App(sgqlc.types.Type, Node): app_store_app_url = sgqlc.types.Field(URL, graphql_name="appStoreAppUrl") app_store_developer_url = sgqlc.types.Field(URL, graphql_name="appStoreDeveloperUrl") available_access_scopes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AccessScope))), - graphql_name="availableAccessScopes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AccessScope))), graphql_name="availableAccessScopes" ) banner = sgqlc.types.Field(sgqlc.types.non_null("Image"), graphql_name="banner") description = sgqlc.types.Field(String, graphql_name="description") @@ -19994,8 +23275,7 @@ class App(sgqlc.types.Type, Node): developer_type = sgqlc.types.Field(sgqlc.types.non_null(AppDeveloperType), graphql_name="developerType") embedded = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="embedded") failed_requirements = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FailedRequirement))), - graphql_name="failedRequirements", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FailedRequirement))), graphql_name="failedRequirements" ) features = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="features") feedback = sgqlc.types.Field(AppFeedback, graphql_name="feedback") @@ -20011,8 +23291,7 @@ class App(sgqlc.types.Type, Node): public_category = sgqlc.types.Field(sgqlc.types.non_null(AppPublicCategory), graphql_name="publicCategory") published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="published") requested_access_scopes = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AccessScope))), - graphql_name="requestedAccessScopes", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AccessScope))), graphql_name="requestedAccessScopes" ) screenshots = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Image"))), graphql_name="screenshots") shopify_developed = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="shopifyDeveloped") @@ -20021,6 +23300,24 @@ class App(sgqlc.types.Type, Node): webhook_api_version = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="webhookApiVersion") +class AppCatalog(sgqlc.types.Type, Catalog, Node): + __schema__ = shopify_schema + __field_names__ = ("apps",) + apps = sgqlc.types.Field( + sgqlc.types.non_null(AppConnection), + graphql_name="apps", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + class AppCredit(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ("amount", "created_at", "description", "test") @@ -20048,8 +23345,7 @@ class AppInstallation(sgqlc.types.Type, HasMetafields, Node): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AccessScope))), graphql_name="accessScopes" ) active_subscriptions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppSubscription"))), - graphql_name="activeSubscriptions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("AppSubscription"))), graphql_name="activeSubscriptions" ) all_subscriptions = sgqlc.types.Field( sgqlc.types.non_null(AppSubscriptionConnection), @@ -20106,10 +23402,7 @@ class AppInstallation(sgqlc.types.Type, HasMetafields, Node): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(AppRevenueAttributionRecordSortKeys, graphql_name="sortKey", default="CREATED_AT"), - ), + ("sort_key", sgqlc.types.Arg(AppRevenueAttributionRecordSortKeys, graphql_name="sortKey", default="CREATED_AT")), ) ), ) @@ -20146,21 +23439,11 @@ class AppRevenueAttributionRecordDeleteUserError(sgqlc.types.Type, DisplayableEr class AppSubscription(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "created_at", - "current_period_end", - "line_items", - "name", - "return_url", - "status", - "test", - "trial_days", - ) + __field_names__ = ("created_at", "current_period_end", "line_items", "name", "return_url", "status", "test", "trial_days") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") current_period_end = sgqlc.types.Field(DateTime, graphql_name="currentPeriodEnd") line_items = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppSubscriptionLineItem))), - graphql_name="lineItems", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AppSubscriptionLineItem))), graphql_name="lineItems" ) name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") return_url = sgqlc.types.Field(sgqlc.types.non_null(URL), graphql_name="returnUrl") @@ -20177,9 +23460,10 @@ class AppSubscriptionTrialExtendUserError(sgqlc.types.Type, DisplayableError): class AppUsageRecord(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("created_at", "description", "price", "subscription_line_item") + __field_names__ = ("created_at", "description", "idempotency_key", "price", "subscription_line_item") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") description = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="description") + idempotency_key = sgqlc.types.Field(String, graphql_name="idempotencyKey") price = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="price") subscription_line_item = sgqlc.types.Field(sgqlc.types.non_null(AppSubscriptionLineItem), graphql_name="subscriptionLineItem") @@ -20351,6 +23635,35 @@ class CalculatedScriptDiscountApplication(sgqlc.types.Type, CalculatedDiscountAp __field_names__ = () +class CartTransform(sgqlc.types.Type, HasMetafields, Node): + __schema__ = shopify_schema + __field_names__ = ("function_id",) + function_id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="functionId") + + +class CartTransformCreateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CartTransformCreateUserErrorCode, graphql_name="code") + + +class CartTransformDeleteUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CartTransformDeleteUserErrorCode, graphql_name="code") + + +class CatalogCsvOperation(sgqlc.types.Type, Node, ResourceOperation): + __schema__ = shopify_schema + __field_names__ = () + + +class CatalogUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CatalogUserErrorCode, graphql_name="code") + + class Channel(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( @@ -20427,9 +23740,10 @@ class Channel(sgqlc.types.Type, Node): class ChannelDefinition(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("channel_name", "handle", "sub_channel_name", "svg_icon") + __field_names__ = ("channel_name", "handle", "is_marketplace", "sub_channel_name", "svg_icon") channel_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="channelName") handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + is_marketplace = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isMarketplace") sub_channel_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="subChannelName") svg_icon = sgqlc.types.Field(String, graphql_name="svgIcon") @@ -20444,8 +23758,9 @@ class ChannelInformation(sgqlc.types.Type, Node): class CheckoutProfile(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("created_at", "is_published", "name", "updated_at") + __field_names__ = ("created_at", "edited_at", "is_published", "name", "updated_at") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + edited_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="editedAt") is_published = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isPublished") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") @@ -20495,10 +23810,7 @@ class Collection(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, HasPu ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(ProductCollectionSortKeys, graphql_name="sortKey", default="COLLECTION_DEFAULT"), - ), + ("sort_key", sgqlc.types.Arg(ProductCollectionSortKeys, graphql_name="sortKey", default="COLLECTION_DEFAULT")), ) ), ) @@ -20521,8 +23833,7 @@ class CommentEvent(sgqlc.types.Type, Event, Node): __schema__ = shopify_schema __field_names__ = ("attachments", "author", "can_delete", "can_edit", "edited", "embed", "raw_message", "subject") attachments = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CommentEventAttachment))), - graphql_name="attachments", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CommentEventAttachment))), graphql_name="attachments" ) author = sgqlc.types.Field(sgqlc.types.non_null("StaffMember"), graphql_name="author") can_delete = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="canDelete") @@ -20533,7 +23844,7 @@ class CommentEvent(sgqlc.types.Type, Event, Node): subject = sgqlc.types.Field(sgqlc.types.non_null(CommentEventSubject), graphql_name="subject") -class Company(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigable, Node): +class Company(sgqlc.types.Type, CommentEventSubject, HasEvents, HasMetafieldDefinitions, HasMetafields, Navigable, Node): __schema__ = shopify_schema __field_names__ = ( "contact_count", @@ -20748,10 +24059,7 @@ class CompanyContact(sgqlc.types.Type, Node): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(CompanyContactRoleAssignmentSortKeys, graphql_name="sortKey", default="ID"), - ), + ("sort_key", sgqlc.types.Arg(CompanyContactRoleAssignmentSortKeys, graphql_name="sortKey", default="ID")), ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), ) ), @@ -20778,16 +24086,18 @@ class CompanyContactRoleAssignment(sgqlc.types.Type, Node): updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") -class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigable, Node): +class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, HasMetafieldDefinitions, HasMetafields, Navigable, Node): __schema__ = shopify_schema __field_names__ = ( "billing_address", "buyer_experience_configuration", + "catalogs", "company", "created_at", "currency", "draft_orders", "external_id", + "in_catalog", "locale", "market", "name", @@ -20804,6 +24114,19 @@ class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigabl ) billing_address = sgqlc.types.Field(CompanyAddress, graphql_name="billingAddress") buyer_experience_configuration = sgqlc.types.Field(BuyerExperienceConfiguration, graphql_name="buyerExperienceConfiguration") + catalogs = sgqlc.types.Field( + sgqlc.types.non_null(CatalogConnection), + graphql_name="catalogs", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) company = sgqlc.types.Field(sgqlc.types.non_null(Company), graphql_name="company") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") currency = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currency") @@ -20823,6 +24146,11 @@ class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigabl ), ) external_id = sgqlc.types.Field(String, graphql_name="externalId") + in_catalog = sgqlc.types.Field( + sgqlc.types.non_null(Boolean), + graphql_name="inCatalog", + args=sgqlc.types.ArgDict((("catalog_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="catalogId", default=None)),)), + ) locale = sgqlc.types.Field(String, graphql_name="locale") market = sgqlc.types.Field(sgqlc.types.non_null("Market"), graphql_name="market") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") @@ -20853,10 +24181,7 @@ class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigabl ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(CompanyContactRoleAssignmentSortKeys, graphql_name="sortKey", default="ID"), - ), + ("sort_key", sgqlc.types.Arg(CompanyContactRoleAssignmentSortKeys, graphql_name="sortKey", default="ID")), ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), ) ), @@ -20870,20 +24195,32 @@ class CompanyLocation(sgqlc.types.Type, CommentEventSubject, HasEvents, Navigabl updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") -class Customer( - sgqlc.types.Type, - CommentEventSubject, - HasEvents, - HasMetafieldDefinitions, - HasMetafields, - LegacyInteroperability, - Node, -): +class CompanyLocationCatalog(sgqlc.types.Type, Catalog, Node): + __schema__ = shopify_schema + __field_names__ = ("company_locations", "company_locations_count") + company_locations = sgqlc.types.Field( + sgqlc.types.non_null(CompanyLocationConnection), + graphql_name="companyLocations", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("sort_key", sgqlc.types.Arg(CompanyLocationSortKeys, graphql_name="sortKey", default="ID")), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) + company_locations_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="companyLocationsCount") + + +class Customer(sgqlc.types.Type, CommentEventSubject, HasEvents, HasMetafieldDefinitions, HasMetafields, LegacyInteroperability, Node): __schema__ = shopify_schema __field_names__ = ( "addresses", "amount_spent", - "average_order_amount_v2", "can_delete", "company_contact_profiles", "created_at", @@ -20898,6 +24235,7 @@ class Customer( "lifetime_duration", "locale", "market", + "mergeable", "multipass_identifier", "note", "number_of_orders", @@ -20923,11 +24261,9 @@ class Customer( args=sgqlc.types.ArgDict((("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)),)), ) amount_spent = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="amountSpent") - average_order_amount_v2 = sgqlc.types.Field(MoneyV2, graphql_name="averageOrderAmountV2") can_delete = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="canDelete") company_contact_profiles = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CompanyContact))), - graphql_name="companyContactProfiles", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CompanyContact))), graphql_name="companyContactProfiles" ) created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") default_address = sgqlc.types.Field("MailingAddress", graphql_name="defaultAddress") @@ -20941,6 +24277,7 @@ class Customer( lifetime_duration = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="lifetimeDuration") locale = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="locale") market = sgqlc.types.Field("Market", graphql_name="market") + mergeable = sgqlc.types.Field(sgqlc.types.non_null(CustomerMergeable), graphql_name="mergeable") multipass_identifier = sgqlc.types.Field(String, graphql_name="multipassIdentifier") note = sgqlc.types.Field(String, graphql_name="note") number_of_orders = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="numberOfOrders") @@ -21010,6 +24347,12 @@ class CustomerEmailMarketingConsentUpdateUserError(sgqlc.types.Type, Displayable code = sgqlc.types.Field(CustomerEmailMarketingConsentUpdateUserErrorCode, graphql_name="code") +class CustomerMergeUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CustomerMergeErrorCode, graphql_name="code") + + class CustomerPaymentMethod(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ("customer", "instrument", "revoked_at", "revoked_reason", "subscription_contracts") @@ -21032,6 +24375,18 @@ class CustomerPaymentMethod(sgqlc.types.Type, Node): ) +class CustomerPaymentMethodCreateFromDuplicationDataUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CustomerPaymentMethodCreateFromDuplicationDataUserErrorCode, graphql_name="code") + + +class CustomerPaymentMethodGetDuplicationDataUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CustomerPaymentMethodGetDuplicationDataUserErrorCode, graphql_name="code") + + class CustomerPaymentMethodGetUpdateUrlUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -21050,6 +24405,48 @@ class CustomerPaymentMethodUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(CustomerPaymentMethodUserErrorCode, graphql_name="code") +class CustomerSegmentMember(sgqlc.types.Type, HasMetafields): + __schema__ = shopify_schema + __field_names__ = ( + "amount_spent", + "default_address", + "default_email_address", + "default_phone_number", + "display_name", + "first_name", + "id", + "last_name", + "last_order_id", + "mergeable", + "note", + "number_of_orders", + ) + amount_spent = sgqlc.types.Field(MoneyV2, graphql_name="amountSpent") + default_address = sgqlc.types.Field("MailingAddress", graphql_name="defaultAddress") + default_email_address = sgqlc.types.Field(CustomerEmailAddress, graphql_name="defaultEmailAddress") + default_phone_number = sgqlc.types.Field(CustomerPhoneNumber, graphql_name="defaultPhoneNumber") + display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") + first_name = sgqlc.types.Field(String, graphql_name="firstName") + id = sgqlc.types.Field(sgqlc.types.non_null(ID), graphql_name="id") + last_name = sgqlc.types.Field(String, graphql_name="lastName") + last_order_id = sgqlc.types.Field(ID, graphql_name="lastOrderId") + mergeable = sgqlc.types.Field(sgqlc.types.non_null(CustomerMergeable), graphql_name="mergeable") + note = sgqlc.types.Field(String, graphql_name="note") + number_of_orders = sgqlc.types.Field(UnsignedInt64, graphql_name="numberOfOrders") + + +class CustomerSegmentMembersQuery(sgqlc.types.Type, JobResult, Node): + __schema__ = shopify_schema + __field_names__ = ("current_count",) + current_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="currentCount") + + +class CustomerSegmentMembersQueryUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(CustomerSegmentMembersQueryUserErrorCode, graphql_name="code") + + class CustomerSmsMarketingConsentError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -21088,6 +24485,12 @@ class DelegateAccessTokenCreateUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(DelegateAccessTokenCreateUserErrorCode, graphql_name="code") +class DelegateAccessTokenDestroyUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(DelegateAccessTokenDestroyUserErrorCode, graphql_name="code") + + class DeliveryCarrierService(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ("available_services_for_countries", "formatted_name", "icon", "name") @@ -21096,22 +24499,12 @@ class DeliveryCarrierService(sgqlc.types.Type, Node): graphql_name="availableServicesForCountries", args=sgqlc.types.ArgDict( ( - ( - "origins", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="origins", default=None), - ), + ("origins", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="origins", default=None)), ( "country_codes", - sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(CountryCode)), - graphql_name="countryCodes", - default=None, - ), - ), - ( - "rest_of_world", - sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="restOfWorld", default=None), + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(CountryCode)), graphql_name="countryCodes", default=None), ), + ("rest_of_world", sgqlc.types.Arg(sgqlc.types.non_null(Boolean), graphql_name="restOfWorld", default=None)), ) ), ) @@ -21139,9 +24532,25 @@ class DeliveryCountry(sgqlc.types.Type, Node): translated_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="translatedName") +class DeliveryCustomization(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, Node): + __schema__ = shopify_schema + __field_names__ = ("enabled", "error_history", "function_id", "shopify_function", "title") + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") + error_history = sgqlc.types.Field(FunctionsErrorHistory, graphql_name="errorHistory") + function_id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="functionId") + shopify_function = sgqlc.types.Field(sgqlc.types.non_null(ShopifyFunction), graphql_name="shopifyFunction") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + +class DeliveryCustomizationError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(DeliveryCustomizationErrorCode, graphql_name="code") + + class DeliveryLocationGroup(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("locations",) + __field_names__ = ("locations", "locations_count") locations = sgqlc.types.Field( sgqlc.types.non_null(LocationConnection), graphql_name="locations", @@ -21159,11 +24568,19 @@ class DeliveryLocationGroup(sgqlc.types.Type, Node): ) ), ) + locations_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="locationsCount") + + +class DeliveryLocationLocalPickupSettingsError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(DeliveryLocationLocalPickupSettingsErrorCode, graphql_name="code") class DeliveryMethod(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("max_delivery_date_time", "method_type", "min_delivery_date_time") + __field_names__ = ("branded_promise", "max_delivery_date_time", "method_type", "min_delivery_date_time") + branded_promise = sgqlc.types.Field(DeliveryBrandedPromise, graphql_name="brandedPromise") max_delivery_date_time = sgqlc.types.Field(DateTime, graphql_name="maxDeliveryDateTime") method_type = sgqlc.types.Field(sgqlc.types.non_null(DeliveryMethodType), graphql_name="methodType") min_delivery_date_time = sgqlc.types.Field(DateTime, graphql_name="minDeliveryDateTime") @@ -21175,8 +24592,7 @@ class DeliveryMethodDefinition(sgqlc.types.Type, Node): active = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="active") description = sgqlc.types.Field(String, graphql_name="description") method_conditions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryCondition))), - graphql_name="methodConditions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryCondition))), graphql_name="methodConditions" ) name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") rate_provider = sgqlc.types.Field(sgqlc.types.non_null("DeliveryRateProvider"), graphql_name="rateProvider") @@ -21184,19 +24600,12 @@ class DeliveryMethodDefinition(sgqlc.types.Type, Node): class DeliveryParticipant(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "adapt_to_new_services_flag", - "carrier_service", - "fixed_fee", - "participant_services", - "percentage_of_rate_fee", - ) + __field_names__ = ("adapt_to_new_services_flag", "carrier_service", "fixed_fee", "participant_services", "percentage_of_rate_fee") adapt_to_new_services_flag = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="adaptToNewServicesFlag") carrier_service = sgqlc.types.Field(sgqlc.types.non_null(DeliveryCarrierService), graphql_name="carrierService") fixed_fee = sgqlc.types.Field(MoneyV2, graphql_name="fixedFee") participant_services = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryParticipantService))), - graphql_name="participantServices", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryParticipantService))), graphql_name="participantServices" ) percentage_of_rate_fee = sgqlc.types.Field(sgqlc.types.non_null(Float), graphql_name="percentageOfRateFee") @@ -21215,6 +24624,7 @@ class DeliveryProfile(sgqlc.types.Type, Node): "profile_location_groups", "selling_plan_groups", "unassigned_locations", + "unassigned_locations_paginated", "zone_country_count", ) active_method_definitions_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="activeMethodDefinitionsCount") @@ -21240,6 +24650,7 @@ class DeliveryProfile(sgqlc.types.Type, Node): profile_location_groups = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DeliveryProfileLocationGroup))), graphql_name="profileLocationGroups", + args=sgqlc.types.ArgDict((("location_group_id", sgqlc.types.Arg(ID, graphql_name="locationGroupId", default=None)),)), ) selling_plan_groups = sgqlc.types.Field( sgqlc.types.non_null(SellingPlanGroupConnection), @@ -21257,6 +24668,19 @@ class DeliveryProfile(sgqlc.types.Type, Node): unassigned_locations = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Location"))), graphql_name="unassignedLocations" ) + unassigned_locations_paginated = sgqlc.types.Field( + sgqlc.types.non_null(LocationConnection), + graphql_name="unassignedLocationsPaginated", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) zone_country_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="zoneCountryCount") @@ -21316,6 +24740,7 @@ class DiscountAutomaticBxgy(sgqlc.types.Type, HasEvents, Node): "status", "summary", "title", + "updated_at", "uses_per_order_limit", ) async_usage_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="asyncUsageCount") @@ -21329,6 +24754,7 @@ class DiscountAutomaticBxgy(sgqlc.types.Type, HasEvents, Node): status = sgqlc.types.Field(sgqlc.types.non_null(DiscountStatus), graphql_name="status") summary = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="summary") title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") uses_per_order_limit = sgqlc.types.Field(Int, graphql_name="usesPerOrderLimit") @@ -21404,14 +24830,7 @@ class Domain(sgqlc.types.Type, Node): class DraftOrder( - sgqlc.types.Type, - CommentEventSubject, - HasEvents, - HasLocalizationExtensions, - HasMetafields, - LegacyInteroperability, - Navigable, - Node, + sgqlc.types.Type, CommentEventSubject, HasEvents, HasLocalizationExtensions, HasMetafields, LegacyInteroperability, Navigable, Node ): __schema__ = shopify_schema __field_names__ = ( @@ -21436,6 +24855,7 @@ class DraftOrder( "order", "payment_terms", "phone", + "po_number", "presentment_currency_code", "purchasing_entity", "ready", @@ -21498,6 +24918,7 @@ class DraftOrder( order = sgqlc.types.Field("Order", graphql_name="order") payment_terms = sgqlc.types.Field("PaymentTerms", graphql_name="paymentTerms") phone = sgqlc.types.Field(String, graphql_name="phone") + po_number = sgqlc.types.Field(String, graphql_name="poNumber") presentment_currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="presentmentCurrencyCode") purchasing_entity = sgqlc.types.Field("PurchasingEntity", graphql_name="purchasingEntity") ready = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="ready") @@ -21563,8 +24984,7 @@ class DraftOrderLineItem(sgqlc.types.Type, Node): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" ) custom_attributes_v2 = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TypedAttribute))), - graphql_name="customAttributesV2", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TypedAttribute))), graphql_name="customAttributesV2" ) discounted_total = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="discountedTotal") discounted_total_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedTotalSet") @@ -21615,12 +25035,48 @@ class DutySale(sgqlc.types.Type, Sale): duty = sgqlc.types.Field(sgqlc.types.non_null(Duty), graphql_name="duty") +class ErrorsServerPixelUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ErrorsServerPixelUserErrorCode, graphql_name="code") + + class ErrorsWebPixelUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) code = sgqlc.types.Field(ErrorsWebPixelUserErrorCode, graphql_name="code") +class ExchangeV2(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "additions", + "completed_at", + "created_at", + "location", + "note", + "refunds", + "returns", + "staff_member", + "total_amount_processed_set", + "total_price_set", + "transactions", + ) + additions = sgqlc.types.Field(sgqlc.types.non_null(ExchangeV2Additions), graphql_name="additions") + completed_at = sgqlc.types.Field(DateTime, graphql_name="completedAt") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + location = sgqlc.types.Field("Location", graphql_name="location") + note = sgqlc.types.Field(String, graphql_name="note") + refunds = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("Refund"))), graphql_name="refunds") + returns = sgqlc.types.Field(sgqlc.types.non_null(ExchangeV2Returns), graphql_name="returns") + staff_member = sgqlc.types.Field("StaffMember", graphql_name="staffMember") + total_amount_processed_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalAmountProcessedSet") + total_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalPriceSet") + transactions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("OrderTransaction"))), graphql_name="transactions" + ) + + class ExternalVideo(sgqlc.types.Type, Media, Node): __schema__ = shopify_schema __field_names__ = ("embed_url", "host", "origin_url") @@ -21720,9 +25176,30 @@ class Fulfillment(sgqlc.types.Type, LegacyInteroperability, Node): class FulfillmentEvent(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("happened_at", "status") + __field_names__ = ( + "address1", + "city", + "country", + "estimated_delivery_at", + "happened_at", + "latitude", + "longitude", + "message", + "province", + "status", + "zip", + ) + address1 = sgqlc.types.Field(String, graphql_name="address1") + city = sgqlc.types.Field(String, graphql_name="city") + country = sgqlc.types.Field(String, graphql_name="country") + estimated_delivery_at = sgqlc.types.Field(DateTime, graphql_name="estimatedDeliveryAt") happened_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="happenedAt") + latitude = sgqlc.types.Field(Float, graphql_name="latitude") + longitude = sgqlc.types.Field(Float, graphql_name="longitude") + message = sgqlc.types.Field(String, graphql_name="message") + province = sgqlc.types.Field(String, graphql_name="province") status = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentEventStatus), graphql_name="status") + zip = sgqlc.types.Field(String, graphql_name="zip") class FulfillmentLineItem(sgqlc.types.Type, Node): @@ -21738,6 +25215,7 @@ class FulfillmentOrder(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( "assigned_location", + "created_at", "delivery_method", "destination", "fulfill_at", @@ -21752,15 +25230,16 @@ class FulfillmentOrder(sgqlc.types.Type, Node): "request_status", "status", "supported_actions", + "updated_at", ) assigned_location = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentOrderAssignedLocation), graphql_name="assignedLocation") + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") delivery_method = sgqlc.types.Field(DeliveryMethod, graphql_name="deliveryMethod") destination = sgqlc.types.Field("FulfillmentOrderDestination", graphql_name="destination") fulfill_at = sgqlc.types.Field(DateTime, graphql_name="fulfillAt") fulfill_by = sgqlc.types.Field(DateTime, graphql_name="fulfillBy") fulfillment_holds = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentHold))), - graphql_name="fulfillmentHolds", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentHold))), graphql_name="fulfillmentHolds" ) fulfillments = sgqlc.types.Field( sgqlc.types.non_null(FulfillmentConnection), @@ -21820,9 +25299,9 @@ class FulfillmentOrder(sgqlc.types.Type, Node): request_status = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentOrderRequestStatus), graphql_name="requestStatus") status = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentOrderStatus), graphql_name="status") supported_actions = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderSupportedAction))), - graphql_name="supportedActions", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderSupportedAction))), graphql_name="supportedActions" ) + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") class FulfillmentOrderDestination(sgqlc.types.Type, Node): @@ -21861,19 +25340,46 @@ class FulfillmentOrderHoldUserError(sgqlc.types.Type, DisplayableError): class FulfillmentOrderLineItem(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("line_item", "remaining_quantity", "total_quantity", "warnings") - line_item = sgqlc.types.Field(sgqlc.types.non_null("LineItem"), graphql_name="lineItem") + __field_names__ = ( + "image", + "inventory_item_id", + "original_unit_price_set", + "product_title", + "remaining_quantity", + "requires_shipping", + "sku", + "total_quantity", + "variant_title", + "vendor", + "warnings", + "weight", + ) + image = sgqlc.types.Field("Image", graphql_name="image") + inventory_item_id = sgqlc.types.Field(ID, graphql_name="inventoryItemId") + original_unit_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="originalUnitPriceSet") + product_title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="productTitle") remaining_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="remainingQuantity") + requires_shipping = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="requiresShipping") + sku = sgqlc.types.Field(String, graphql_name="sku") total_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="totalQuantity") + variant_title = sgqlc.types.Field(String, graphql_name="variantTitle") + vendor = sgqlc.types.Field(String, graphql_name="vendor") warnings = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemWarning))), - graphql_name="warnings", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentOrderLineItemWarning))), graphql_name="warnings" ) + weight = sgqlc.types.Field(Weight, graphql_name="weight") + + +class FulfillmentOrderLineItemsPreparedForPickupUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(FulfillmentOrderLineItemsPreparedForPickupUserErrorCode, graphql_name="code") class FulfillmentOrderMerchantRequest(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("kind", "message", "request_options", "response_data", "sent_at") + __field_names__ = ("fulfillment_order", "kind", "message", "request_options", "response_data", "sent_at") + fulfillment_order = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentOrder), graphql_name="fulfillmentOrder") kind = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentOrderMerchantRequestKind), graphql_name="kind") message = sgqlc.types.Field(String, graphql_name="message") request_options = sgqlc.types.Field(JSON, graphql_name="requestOptions") @@ -21881,6 +25387,12 @@ class FulfillmentOrderMerchantRequest(sgqlc.types.Type, Node): sent_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="sentAt") +class FulfillmentOrderMergeUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(FulfillmentOrderMergeUserErrorCode, graphql_name="code") + + class FulfillmentOrderReleaseHoldUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -21893,6 +25405,18 @@ class FulfillmentOrderRescheduleUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(FulfillmentOrderRescheduleUserErrorCode, graphql_name="code") +class FulfillmentOrderSplitUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(FulfillmentOrderSplitUserErrorCode, graphql_name="code") + + +class FulfillmentOrdersReleaseHoldsUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(FulfillmentOrdersReleaseHoldsUserErrorCode, graphql_name="code") + + class FulfillmentOrdersSetFulfillmentDeadlineUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -21961,6 +25485,39 @@ class Image(sgqlc.types.Type, HasMetafields): width = sgqlc.types.Field(Int, graphql_name="width") +class InventoryAdjustQuantitiesUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(InventoryAdjustQuantitiesUserErrorCode, graphql_name="code") + + +class InventoryAdjustmentGroup(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("app", "changes", "created_at", "reason", "reference_document_uri", "staff_member") + app = sgqlc.types.Field(App, graphql_name="app") + changes = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(InventoryChange))), + graphql_name="changes", + args=sgqlc.types.ArgDict( + ( + ( + "inventory_item_ids", + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="inventoryItemIds", default=None), + ), + ("location_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationIds", default=None)), + ( + "quantity_names", + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(String)), graphql_name="quantityNames", default=None), + ), + ) + ), + ) + created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") + reason = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="reason") + reference_document_uri = sgqlc.types.Field(String, graphql_name="referenceDocumentUri") + staff_member = sgqlc.types.Field("StaffMember", graphql_name="staffMember") + + class InventoryBulkToggleActivationUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -22038,28 +25595,41 @@ class InventoryItem(sgqlc.types.Type, LegacyInteroperability, Node): class InventoryLevel(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "available", - "can_deactivate", - "created_at", - "deactivation_alert", - "deactivation_alert_html", - "incoming", - "item", - "location", - "updated_at", - ) - available = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="available") + __field_names__ = ("can_deactivate", "created_at", "deactivation_alert", "item", "location", "quantities", "updated_at") can_deactivate = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="canDeactivate") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") deactivation_alert = sgqlc.types.Field(String, graphql_name="deactivationAlert") - deactivation_alert_html = sgqlc.types.Field(FormattedString, graphql_name="deactivationAlertHtml") - incoming = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="incoming") item = sgqlc.types.Field(sgqlc.types.non_null(InventoryItem), graphql_name="item") location = sgqlc.types.Field(sgqlc.types.non_null("Location"), graphql_name="location") + quantities = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(InventoryQuantity))), + graphql_name="quantities", + args=sgqlc.types.ArgDict( + ( + ( + "names", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="names", default=None + ), + ), + ) + ), + ) updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") +class InventoryMoveQuantitiesUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(InventoryMoveQuantitiesUserErrorCode, graphql_name="code") + + +class InventorySetOnHandQuantitiesUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(InventorySetOnHandQuantitiesUserErrorCode, graphql_name="code") + + class LineItem(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( @@ -22071,6 +25641,7 @@ class LineItem(sgqlc.types.Type, Node): "discounted_unit_price_set", "duties", "image", + "line_item_group", "merchant_editable", "name", "non_fulfillable_quantity", @@ -22101,13 +25672,13 @@ class LineItem(sgqlc.types.Type, Node): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" ) discount_allocations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), - graphql_name="discountAllocations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), graphql_name="discountAllocations" ) discounted_total_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedTotalSet") discounted_unit_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedUnitPriceSet") duties = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Duty))), graphql_name="duties") image = sgqlc.types.Field(Image, graphql_name="image") + line_item_group = sgqlc.types.Field(LineItemGroup, graphql_name="lineItemGroup") merchant_editable = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="merchantEditable") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") non_fulfillable_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="nonFulfillableQuantity") @@ -22175,8 +25746,7 @@ class LineItemMutable(sgqlc.types.Type, Node): sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(Attribute))), graphql_name="customAttributes" ) discount_allocations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), - graphql_name="discountAllocations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(DiscountAllocation))), graphql_name="discountAllocations" ) discounted_total_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedTotalSet") discounted_unit_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="discountedUnitPriceSet") @@ -22235,6 +25805,7 @@ class Location(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, LegacyI "inventory_level", "inventory_levels", "is_active", + "local_pickup_settings_v2", "name", "ships_inventory", "suggested_addresses", @@ -22253,12 +25824,7 @@ class Location(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, LegacyI InventoryLevel, graphql_name="inventoryLevel", args=sgqlc.types.ArgDict( - ( - ( - "inventory_item_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None), - ), - ) + (("inventory_item_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="inventoryItemId", default=None)),) ), ) inventory_levels = sgqlc.types.Field( @@ -22276,11 +25842,11 @@ class Location(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, LegacyI ), ) is_active = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="isActive") + local_pickup_settings_v2 = sgqlc.types.Field(DeliveryLocalPickupSettings, graphql_name="localPickupSettingsV2") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") ships_inventory = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="shipsInventory") suggested_addresses = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(LocationSuggestedAddress))), - graphql_name="suggestedAddresses", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(LocationSuggestedAddress))), graphql_name="suggestedAddresses" ) @@ -22334,6 +25900,7 @@ class MailingAddress(sgqlc.types.Type, Node): "phone", "province", "province_code", + "time_zone", "zip", ) address1 = sgqlc.types.Field(String, graphql_name="address1") @@ -22362,6 +25929,7 @@ class MailingAddress(sgqlc.types.Type, Node): phone = sgqlc.types.Field(String, graphql_name="phone") province = sgqlc.types.Field(String, graphql_name="province") province_code = sgqlc.types.Field(String, graphql_name="provinceCode") + time_zone = sgqlc.types.Field(String, graphql_name="timeZone") zip = sgqlc.types.Field(String, graphql_name="zip") @@ -22372,11 +25940,25 @@ class ManualDiscountApplication(sgqlc.types.Type, DiscountApplication): title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") -class Market(sgqlc.types.Type, Node): +class Market(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, Node): __schema__ = shopify_schema - __field_names__ = ("currency_settings", "enabled", "name", "price_list", "primary", "regions", "web_presence") + __field_names__ = ("catalogs", "currency_settings", "enabled", "handle", "name", "price_list", "primary", "regions", "web_presence") + catalogs = sgqlc.types.Field( + sgqlc.types.non_null(MarketCatalogConnection), + graphql_name="catalogs", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) currency_settings = sgqlc.types.Field(sgqlc.types.non_null(MarketCurrencySettings), graphql_name="currencySettings") enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") price_list = sgqlc.types.Field("PriceList", graphql_name="priceList") primary = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="primary") @@ -22396,6 +25978,24 @@ class Market(sgqlc.types.Type, Node): web_presence = sgqlc.types.Field("MarketWebPresence", graphql_name="webPresence") +class MarketCatalog(sgqlc.types.Type, Catalog, Node): + __schema__ = shopify_schema + __field_names__ = ("markets",) + markets = sgqlc.types.Field( + sgqlc.types.non_null(MarketConnection), + graphql_name="markets", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + class MarketCurrencySettingsUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -22404,8 +26004,9 @@ class MarketCurrencySettingsUserError(sgqlc.types.Type, DisplayableError): class MarketRegionCountry(sgqlc.types.Type, MarketRegion, Node): __schema__ = shopify_schema - __field_names__ = ("code",) + __field_names__ = ("code", "currency") code = sgqlc.types.Field(sgqlc.types.non_null(CountryCode), graphql_name="code") + currency = sgqlc.types.Field(sgqlc.types.non_null(CurrencySetting), graphql_name="currency") class MarketUserError(sgqlc.types.Type, DisplayableError): @@ -22424,8 +26025,7 @@ class MarketWebPresence(sgqlc.types.Type, Node): domain = sgqlc.types.Field(Domain, graphql_name="domain") market = sgqlc.types.Field(sgqlc.types.non_null(Market), graphql_name="market") root_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MarketWebPresenceRootUrl))), - graphql_name="rootUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MarketWebPresenceRootUrl))), graphql_name="rootUrls" ) subfolder_suffix = sgqlc.types.Field(String, graphql_name="subfolderSuffix") @@ -22516,7 +26116,7 @@ class MarketingEvent(sgqlc.types.Type, LegacyInteroperability, Node): utm_source = sgqlc.types.Field(String, graphql_name="utmSource") -class MediaImage(sgqlc.types.Type, File, Media, Node): +class MediaImage(sgqlc.types.Type, File, HasMetafields, Media, Node): __schema__ = shopify_schema __field_names__ = ("image", "mime_type", "original_source") image = sgqlc.types.Field(Image, graphql_name="image") @@ -22574,6 +26174,7 @@ class Metafield(sgqlc.types.Type, LegacyInteroperability, Node): class MetafieldDefinition(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( + "access", "description", "key", "metafields", @@ -22584,10 +26185,12 @@ class MetafieldDefinition(sgqlc.types.Type, Node): "pinned_position", "standard_template", "type", + "use_as_collection_condition", "validation_status", "validations", "visible_to_storefront_api", ) + access = sgqlc.types.Field(sgqlc.types.non_null(MetafieldAccess), graphql_name="access") description = sgqlc.types.Field(String, graphql_name="description") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") metafields = sgqlc.types.Field( @@ -22595,10 +26198,7 @@ class MetafieldDefinition(sgqlc.types.Type, Node): graphql_name="metafields", args=sgqlc.types.ArgDict( ( - ( - "validation_status", - sgqlc.types.Arg(MetafieldValidationStatus, graphql_name="validationStatus", default="ANY"), - ), + ("validation_status", sgqlc.types.Arg(MetafieldValidationStatus, graphql_name="validationStatus", default="ANY")), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -22611,12 +26211,7 @@ class MetafieldDefinition(sgqlc.types.Type, Node): sgqlc.types.non_null(Int), graphql_name="metafieldsCount", args=sgqlc.types.ArgDict( - ( - ( - "validation_status", - sgqlc.types.Arg(MetafieldValidationStatus, graphql_name="validationStatus", default=None), - ), - ) + (("validation_status", sgqlc.types.Arg(MetafieldValidationStatus, graphql_name="validationStatus", default=None)),) ), ) name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") @@ -22625,10 +26220,10 @@ class MetafieldDefinition(sgqlc.types.Type, Node): pinned_position = sgqlc.types.Field(Int, graphql_name="pinnedPosition") standard_template = sgqlc.types.Field("StandardMetafieldDefinitionTemplate", graphql_name="standardTemplate") type = sgqlc.types.Field(sgqlc.types.non_null(MetafieldDefinitionType), graphql_name="type") + use_as_collection_condition = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="useAsCollectionCondition") validation_status = sgqlc.types.Field(sgqlc.types.non_null(MetafieldDefinitionValidationStatus), graphql_name="validationStatus") validations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidation))), - graphql_name="validations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidation))), graphql_name="validations" ) visible_to_storefront_api = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="visibleToStorefrontApi") @@ -22680,6 +26275,94 @@ class MetafieldsSetUserError(sgqlc.types.Type, DisplayableError): element_index = sgqlc.types.Field(Int, graphql_name="elementIndex") +class Metaobject(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "capabilities", + "created_by", + "definition", + "display_name", + "field", + "fields", + "handle", + "referenced_by", + "type", + "updated_at", + ) + capabilities = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectCapabilityData), graphql_name="capabilities") + created_by = sgqlc.types.Field(sgqlc.types.non_null(App), graphql_name="createdBy") + definition = sgqlc.types.Field(sgqlc.types.non_null("MetaobjectDefinition"), graphql_name="definition") + display_name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="displayName") + field = sgqlc.types.Field( + MetaobjectField, + graphql_name="field", + args=sgqlc.types.ArgDict((("key", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="key", default=None)),)), + ) + fields = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetaobjectField))), graphql_name="fields") + handle = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="handle") + referenced_by = sgqlc.types.Field( + sgqlc.types.non_null(MetafieldRelationConnection), + graphql_name="referencedBy", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") + + +class MetaobjectDefinition(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "access", + "capabilities", + "description", + "display_name_key", + "field_definitions", + "metaobjects", + "metaobjects_count", + "name", + "type", + ) + access = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectAccess), graphql_name="access") + capabilities = sgqlc.types.Field(sgqlc.types.non_null(MetaobjectCapabilities), graphql_name="capabilities") + description = sgqlc.types.Field(String, graphql_name="description") + display_name_key = sgqlc.types.Field(String, graphql_name="displayNameKey") + field_definitions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetaobjectFieldDefinition))), graphql_name="fieldDefinitions" + ) + metaobjects = sgqlc.types.Field( + sgqlc.types.non_null(MetaobjectConnection), + graphql_name="metaobjects", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + metaobjects_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="metaobjectsCount") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="type") + + +class MetaobjectUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code", "element_index", "element_key") + code = sgqlc.types.Field(MetaobjectUserErrorCode, graphql_name="code") + element_index = sgqlc.types.Field(Int, graphql_name="elementIndex") + element_key = sgqlc.types.Field(String, graphql_name="elementKey") + + class Model3d(sgqlc.types.Type, Media, Node): __schema__ = shopify_schema __field_names__ = ("bounding_box", "filename", "original_source", "sources") @@ -22716,6 +26399,7 @@ class Order( ): __schema__ = shopify_schema __field_names__ = ( + "additional_fees", "agreements", "alerts", "app", @@ -22731,6 +26415,7 @@ class Order( "client_ip", "closed", "closed_at", + "confirmation_number", "confirmed", "created_at", "currency_code", @@ -22738,6 +26423,7 @@ class Order( "current_subtotal_line_items_quantity", "current_subtotal_price_set", "current_tax_lines", + "current_total_additional_fees_set", "current_total_discounts_set", "current_total_duties_set", "current_total_price_set", @@ -22758,6 +26444,7 @@ class Order( "edited", "email", "estimated_taxes", + "exchange_v2s", "fulfillable", "fulfillment_orders", "fulfillments", @@ -22770,6 +26457,7 @@ class Order( "net_payment_set", "non_fulfillable_line_items", "note", + "original_total_additional_fees_set", "original_total_duties_set", "original_total_price_set", "payment_collection_details", @@ -22777,6 +26465,7 @@ class Order( "payment_terms", "phone", "physical_location", + "po_number", "presentment_currency_code", "processed_at", "publication", @@ -22787,6 +26476,8 @@ class Order( "registered_source_url", "requires_shipping", "restockable", + "return_status", + "returns", "risk_level", "risks", "shipping_address", @@ -22797,6 +26488,7 @@ class Order( "subtotal_price_set", "suggested_refund", "tags", + "tax_exempt", "tax_lines", "taxes_included", "test", @@ -22815,6 +26507,9 @@ class Order( "unpaid", "updated_at", ) + additional_fees = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AdditionalFee))), graphql_name="additionalFees" + ) agreements = sgqlc.types.Field( sgqlc.types.non_null(SalesAgreementConnection), graphql_name="agreements", @@ -22845,6 +26540,7 @@ class Order( client_ip = sgqlc.types.Field(String, graphql_name="clientIp") closed = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="closed") closed_at = sgqlc.types.Field(DateTime, graphql_name="closedAt") + confirmation_number = sgqlc.types.Field(String, graphql_name="confirmationNumber") confirmed = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="confirmed") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currencyCode") @@ -22854,6 +26550,7 @@ class Order( current_tax_lines = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TaxLine))), graphql_name="currentTaxLines" ) + current_total_additional_fees_set = sgqlc.types.Field(MoneyBag, graphql_name="currentTotalAdditionalFeesSet") current_total_discounts_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="currentTotalDiscountsSet") current_total_duties_set = sgqlc.types.Field(MoneyBag, graphql_name="currentTotalDutiesSet") current_total_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="currentTotalPriceSet") @@ -22894,6 +26591,20 @@ class Order( edited = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="edited") email = sgqlc.types.Field(String, graphql_name="email") estimated_taxes = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="estimatedTaxes") + exchange_v2s = sgqlc.types.Field( + sgqlc.types.non_null(ExchangeV2Connection), + graphql_name="exchangeV2s", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) fulfillable = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="fulfillable") fulfillment_orders = sgqlc.types.Field( sgqlc.types.non_null(FulfillmentOrderConnection), @@ -22950,6 +26661,7 @@ class Order( ), ) note = sgqlc.types.Field(String, graphql_name="note") + original_total_additional_fees_set = sgqlc.types.Field(MoneyBag, graphql_name="originalTotalAdditionalFeesSet") original_total_duties_set = sgqlc.types.Field(MoneyBag, graphql_name="originalTotalDutiesSet") original_total_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="originalTotalPriceSet") payment_collection_details = sgqlc.types.Field( @@ -22961,6 +26673,7 @@ class Order( payment_terms = sgqlc.types.Field("PaymentTerms", graphql_name="paymentTerms") phone = sgqlc.types.Field(String, graphql_name="phone") physical_location = sgqlc.types.Field(Location, graphql_name="physicalLocation") + po_number = sgqlc.types.Field(String, graphql_name="poNumber") presentment_currency_code = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="presentmentCurrencyCode") processed_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="processedAt") publication = sgqlc.types.Field("Publication", graphql_name="publication") @@ -22975,6 +26688,21 @@ class Order( registered_source_url = sgqlc.types.Field(URL, graphql_name="registeredSourceUrl") requires_shipping = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="requiresShipping") restockable = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="restockable") + return_status = sgqlc.types.Field(sgqlc.types.non_null(OrderReturnStatus), graphql_name="returnStatus") + returns = sgqlc.types.Field( + sgqlc.types.non_null(ReturnConnection), + graphql_name="returns", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ("query", sgqlc.types.Arg(String, graphql_name="query", default=None)), + ) + ), + ) risk_level = sgqlc.types.Field(sgqlc.types.non_null(OrderRiskLevel), graphql_name="riskLevel") risks = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(OrderRisk))), @@ -23009,24 +26737,19 @@ class Order( ( "refund_line_items", sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(RefundLineItemInput)), - graphql_name="refundLineItems", - default=None, + sgqlc.types.list_of(sgqlc.types.non_null(RefundLineItemInput)), graphql_name="refundLineItems", default=None ), ), ( "refund_duties", - sgqlc.types.Arg( - sgqlc.types.list_of(sgqlc.types.non_null(RefundDutyInput)), - graphql_name="refundDuties", - default=None, - ), + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(RefundDutyInput)), graphql_name="refundDuties", default=None), ), ("suggest_full_refund", sgqlc.types.Arg(Boolean, graphql_name="suggestFullRefund", default=False)), ) ), ) tags = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="tags") + tax_exempt = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="taxExempt") tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TaxLine))), graphql_name="taxLines") taxes_included = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="taxesIncluded") test = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="test") @@ -23103,7 +26826,9 @@ class OrderTransaction(sgqlc.types.Type, Node): "maximum_refundable_v2", "order", "parent_transaction", + "payment_details", "payment_icon", + "payment_id", "processed_at", "receipt_json", "settlement_currency", @@ -23128,7 +26853,9 @@ class OrderTransaction(sgqlc.types.Type, Node): maximum_refundable_v2 = sgqlc.types.Field(MoneyV2, graphql_name="maximumRefundableV2") order = sgqlc.types.Field(Order, graphql_name="order") parent_transaction = sgqlc.types.Field("OrderTransaction", graphql_name="parentTransaction") + payment_details = sgqlc.types.Field("PaymentDetails", graphql_name="paymentDetails") payment_icon = sgqlc.types.Field(Image, graphql_name="paymentIcon") + payment_id = sgqlc.types.Field(String, graphql_name="paymentId") processed_at = sgqlc.types.Field(DateTime, graphql_name="processedAt") receipt_json = sgqlc.types.Field(JSON, graphql_name="receiptJson") settlement_currency = sgqlc.types.Field(CurrencyCode, graphql_name="settlementCurrency") @@ -23140,32 +26867,59 @@ class OrderTransaction(sgqlc.types.Type, Node): user = sgqlc.types.Field("StaffMember", graphql_name="user") +class PaymentCustomization(sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, Node): + __schema__ = shopify_schema + __field_names__ = ("enabled", "error_history", "function_id", "shopify_function", "title") + enabled = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="enabled") + error_history = sgqlc.types.Field(FunctionsErrorHistory, graphql_name="errorHistory") + function_id = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="functionId") + shopify_function = sgqlc.types.Field(sgqlc.types.non_null(ShopifyFunction), graphql_name="shopifyFunction") + title = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="title") + + +class PaymentCustomizationError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(PaymentCustomizationErrorCode, graphql_name="code") + + class PaymentMandate(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ("payment_instrument",) payment_instrument = sgqlc.types.Field(sgqlc.types.non_null("PaymentInstrument"), graphql_name="paymentInstrument") +class PaymentReminderSendUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(PaymentReminderSendUserErrorCode, graphql_name="code") + + class PaymentSchedule(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("amount", "completed_at", "due_at", "issued_at") + __field_names__ = ("amount", "completed_at", "due_at", "issued_at", "payment_terms") amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="amount") completed_at = sgqlc.types.Field(DateTime, graphql_name="completedAt") due_at = sgqlc.types.Field(DateTime, graphql_name="dueAt") issued_at = sgqlc.types.Field(DateTime, graphql_name="issuedAt") + payment_terms = sgqlc.types.Field(sgqlc.types.non_null("PaymentTerms"), graphql_name="paymentTerms") class PaymentTerms(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( + "draft_order", "due_in_days", + "order", "overdue", "payment_schedules", "payment_terms_name", "payment_terms_type", "translated_name", ) + draft_order = sgqlc.types.Field(DraftOrder, graphql_name="draftOrder") due_in_days = sgqlc.types.Field(Int, graphql_name="dueInDays") + order = sgqlc.types.Field(Order, graphql_name="order") overdue = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="overdue") payment_schedules = sgqlc.types.Field( sgqlc.types.non_null(PaymentScheduleConnection), @@ -23213,11 +26967,19 @@ class PaymentTermsUpdateUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(PaymentTermsUpdateUserErrorCode, graphql_name="code") +class PolarisVizResponse(sgqlc.types.Type, ShopifyqlResponse): + __schema__ = shopify_schema + __field_names__ = ("data", "viz_type") + data = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(PolarisVizDataSeries))), graphql_name="data") + viz_type = sgqlc.types.Field(sgqlc.types.non_null(VisualizationType), graphql_name="vizType") + + class PriceList(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("context_rule", "currency", "name", "parent", "prices") - context_rule = sgqlc.types.Field(PriceListContextRule, graphql_name="contextRule") + __field_names__ = ("catalog", "currency", "fixed_prices_count", "name", "parent", "prices", "quantity_rules") + catalog = sgqlc.types.Field(Catalog, graphql_name="catalog") currency = sgqlc.types.Field(sgqlc.types.non_null(CurrencyCode), graphql_name="currency") + fixed_prices_count = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="fixedPricesCount") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") parent = sgqlc.types.Field(PriceListParent, graphql_name="parent") prices = sgqlc.types.Field( @@ -23234,6 +26996,26 @@ class PriceList(sgqlc.types.Type, Node): ) ), ) + quantity_rules = sgqlc.types.Field( + sgqlc.types.non_null(QuantityRuleConnection), + graphql_name="quantityRules", + args=sgqlc.types.ArgDict( + ( + ("origin_type", sgqlc.types.Arg(QuantityRuleOriginType, graphql_name="originType", default=None)), + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + + +class PriceListFixedPricesByProductBulkUpdateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(PriceListFixedPricesByProductBulkUpdateUserErrorCode, graphql_name="code") class PriceListPriceUserError(sgqlc.types.Type, DisplayableError): @@ -23318,8 +27100,7 @@ class PriceRule(sgqlc.types.Type, CommentEventSubject, HasEvents, LegacyInterope PriceRulePrerequisiteToEntitlementQuantityRatio, graphql_name="prerequisiteToEntitlementQuantityRatio" ) shareable_urls = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(PriceRuleShareableUrl))), - graphql_name="shareableUrls", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(PriceRuleShareableUrl))), graphql_name="shareableUrls" ) shipping_entitlements = sgqlc.types.Field(sgqlc.types.non_null(PriceRuleShippingLineEntitlements), graphql_name="shippingEntitlements") starts_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="startsAt") @@ -23395,6 +27176,7 @@ class Product( "product_category", "product_type", "published_at", + "published_in_context", "requires_selling_plan", "resource_publication_on_current_publication", "selling_plan_group_count", @@ -23430,12 +27212,7 @@ class Product( sgqlc.types.non_null(ProductContextualPricing), graphql_name="contextualPricing", args=sgqlc.types.ArgDict( - ( - ( - "context", - sgqlc.types.Arg(sgqlc.types.non_null(ContextualPricingContext), graphql_name="context", default=None), - ), - ) + (("context", sgqlc.types.Arg(sgqlc.types.non_null(ContextualPricingContext), graphql_name="context", default=None)),) ), ) created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") @@ -23497,6 +27274,13 @@ class Product( product_category = sgqlc.types.Field(ProductCategory, graphql_name="productCategory") product_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="productType") published_at = sgqlc.types.Field(DateTime, graphql_name="publishedAt") + published_in_context = sgqlc.types.Field( + sgqlc.types.non_null(Boolean), + graphql_name="publishedInContext", + args=sgqlc.types.ArgDict( + (("context", sgqlc.types.Arg(sgqlc.types.non_null(ContextualPublicationContext), graphql_name="context", default=None)),) + ), + ) requires_selling_plan = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="requiresSellingPlan") resource_publication_on_current_publication = sgqlc.types.Field( ResourcePublicationV2, graphql_name="resourcePublicationOnCurrentPublication" @@ -23547,6 +27331,44 @@ class ProductChangeStatusUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(ProductChangeStatusUserErrorCode, graphql_name="code") +class ProductDeleteUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductDeleteUserErrorCode, graphql_name="code") + + +class ProductDuplicateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductDuplicateUserErrorCode, graphql_name="code") + + +class ProductFeed(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("country", "language", "status") + country = sgqlc.types.Field(CountryCode, graphql_name="country") + language = sgqlc.types.Field(LanguageCode, graphql_name="language") + status = sgqlc.types.Field(sgqlc.types.non_null(ProductFeedStatus), graphql_name="status") + + +class ProductFeedCreateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductFeedCreateUserErrorCode, graphql_name="code") + + +class ProductFeedDeleteUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductFeedDeleteUserErrorCode, graphql_name="code") + + +class ProductFullSyncUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductFullSyncUserErrorCode, graphql_name="code") + + class ProductOption(sgqlc.types.Type, HasPublishedTranslations, Node): __schema__ = shopify_schema __field_names__ = ("name", "position", "values") @@ -23571,13 +27393,7 @@ class ProductTaxonomyNode(sgqlc.types.Type, Node): class ProductVariant( - sgqlc.types.Type, - HasMetafieldDefinitions, - HasMetafields, - HasPublishedTranslations, - LegacyInteroperability, - Navigable, - Node, + sgqlc.types.Type, HasMetafieldDefinitions, HasMetafields, HasPublishedTranslations, LegacyInteroperability, Navigable, Node ): __schema__ = shopify_schema __field_names__ = ( @@ -23597,6 +27413,8 @@ class ProductVariant( "position", "price", "product", + "product_variant_components", + "requires_components", "selected_options", "sellable_online_quantity", "selling_plan_group_count", @@ -23616,12 +27434,7 @@ class ProductVariant( sgqlc.types.non_null(ProductVariantContextualPricing), graphql_name="contextualPricing", args=sgqlc.types.ArgDict( - ( - ( - "context", - sgqlc.types.Arg(sgqlc.types.non_null(ContextualPricingContext), graphql_name="context", default=None), - ), - ) + (("context", sgqlc.types.Arg(sgqlc.types.non_null(ContextualPricingContext), graphql_name="context", default=None)),) ), ) created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") @@ -23648,6 +27461,20 @@ class ProductVariant( position = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="position") price = sgqlc.types.Field(sgqlc.types.non_null(Money), graphql_name="price") product = sgqlc.types.Field(sgqlc.types.non_null(Product), graphql_name="product") + product_variant_components = sgqlc.types.Field( + sgqlc.types.non_null(ProductVariantComponentConnection), + graphql_name="productVariantComponents", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + requires_components = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="requiresComponents") selected_options = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SelectedOption))), graphql_name="selectedOptions" ) @@ -23675,6 +27502,19 @@ class ProductVariant( weight_unit = sgqlc.types.Field(sgqlc.types.non_null(WeightUnit), graphql_name="weightUnit") +class ProductVariantComponent(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("product_variant", "quantity") + product_variant = sgqlc.types.Field(sgqlc.types.non_null(ProductVariant), graphql_name="productVariant") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + + +class ProductVariantRelationshipBulkUpdateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ProductVariantRelationshipBulkUpdateUserErrorCode, graphql_name="code") + + class ProductVariantsBulkCreateUserError(sgqlc.types.Type, DisplayableError): __schema__ = shopify_schema __field_names__ = ("code",) @@ -23714,16 +27554,18 @@ class PubSubWebhookSubscriptionUpdateUserError(sgqlc.types.Type, DisplayableErro class Publication(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( - "app", + "auto_publish", + "catalog", "collection_publications_v3", "collections", "has_collection", - "name", + "operation", "product_publications_v3", "products", "supports_future_publishing", ) - app = sgqlc.types.Field(sgqlc.types.non_null(App), graphql_name="app") + auto_publish = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="autoPublish") + catalog = sgqlc.types.Field(Catalog, graphql_name="catalog") collection_publications_v3 = sgqlc.types.Field( sgqlc.types.non_null(ResourcePublicationConnection), graphql_name="collectionPublicationsV3", @@ -23750,15 +27592,231 @@ class Publication(sgqlc.types.Type, Node): ) ), ) - has_collection = sgqlc.types.Field( - sgqlc.types.non_null(Boolean), - graphql_name="hasCollection", - args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + has_collection = sgqlc.types.Field( + sgqlc.types.non_null(Boolean), + graphql_name="hasCollection", + args=sgqlc.types.ArgDict((("id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="id", default=None)),)), + ) + operation = sgqlc.types.Field("PublicationOperation", graphql_name="operation") + product_publications_v3 = sgqlc.types.Field( + sgqlc.types.non_null(ResourcePublicationConnection), + graphql_name="productPublicationsV3", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + products = sgqlc.types.Field( + sgqlc.types.non_null(ProductConnection), + graphql_name="products", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + supports_future_publishing = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supportsFuturePublishing") + + +class PublicationResourceOperation(sgqlc.types.Type, Node, ResourceOperation): + __schema__ = shopify_schema + __field_names__ = () + + +class PublicationUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(PublicationUserErrorCode, graphql_name="code") + + +class QuantityRuleUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(QuantityRuleUserErrorCode, graphql_name="code") + + +class Refund(sgqlc.types.Type, LegacyInteroperability, Node): + __schema__ = shopify_schema + __field_names__ = ( + "created_at", + "duties", + "note", + "order", + "refund_line_items", + "return_", + "staff_member", + "total_refunded_set", + "transactions", + "updated_at", + ) + created_at = sgqlc.types.Field(DateTime, graphql_name="createdAt") + duties = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(RefundDuty)), graphql_name="duties") + note = sgqlc.types.Field(String, graphql_name="note") + order = sgqlc.types.Field(sgqlc.types.non_null(Order), graphql_name="order") + refund_line_items = sgqlc.types.Field( + sgqlc.types.non_null(RefundLineItemConnection), + graphql_name="refundLineItems", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + return_ = sgqlc.types.Field("Return", graphql_name="return") + staff_member = sgqlc.types.Field("StaffMember", graphql_name="staffMember") + total_refunded_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalRefundedSet") + transactions = sgqlc.types.Field( + sgqlc.types.non_null(OrderTransactionConnection), + graphql_name="transactions", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") + + +class RefundAgreement(sgqlc.types.Type, SalesAgreement): + __schema__ = shopify_schema + __field_names__ = ("refund",) + refund = sgqlc.types.Field(sgqlc.types.non_null(Refund), graphql_name="refund") + + +class Return(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "decline", + "name", + "order", + "refunds", + "return_line_items", + "reverse_fulfillment_orders", + "status", + "suggested_refund", + "total_quantity", + ) + decline = sgqlc.types.Field(ReturnDecline, graphql_name="decline") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + order = sgqlc.types.Field(sgqlc.types.non_null(Order), graphql_name="order") + refunds = sgqlc.types.Field( + sgqlc.types.non_null(RefundConnection), + graphql_name="refunds", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + return_line_items = sgqlc.types.Field( + sgqlc.types.non_null(ReturnLineItemConnection), + graphql_name="returnLineItems", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + reverse_fulfillment_orders = sgqlc.types.Field( + sgqlc.types.non_null(ReverseFulfillmentOrderConnection), + graphql_name="reverseFulfillmentOrders", + args=sgqlc.types.ArgDict( + ( + ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), + ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), + ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), + ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), + ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), + ) + ), + ) + status = sgqlc.types.Field(sgqlc.types.non_null(ReturnStatus), graphql_name="status") + suggested_refund = sgqlc.types.Field( + SuggestedReturnRefund, + graphql_name="suggestedRefund", + args=sgqlc.types.ArgDict( + ( + ( + "return_refund_line_items", + sgqlc.types.Arg( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ReturnRefundLineItemInput))), + graphql_name="returnRefundLineItems", + default=None, + ), + ), + ("refund_shipping", sgqlc.types.Arg(RefundShippingInput, graphql_name="refundShipping", default=None)), + ( + "refund_duties", + sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(RefundDutyInput)), graphql_name="refundDuties", default=None), + ), + ) + ), ) - name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") - product_publications_v3 = sgqlc.types.Field( - sgqlc.types.non_null(ResourcePublicationConnection), - graphql_name="productPublicationsV3", + total_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="totalQuantity") + + +class ReturnLineItem(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "customer_note", + "fulfillment_line_item", + "quantity", + "refundable_quantity", + "refunded_quantity", + "return_reason", + "return_reason_note", + "total_weight", + "with_code_discounted_total_price_set", + ) + customer_note = sgqlc.types.Field(String, graphql_name="customerNote") + fulfillment_line_item = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentLineItem), graphql_name="fulfillmentLineItem") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + refundable_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="refundableQuantity") + refunded_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="refundedQuantity") + return_reason = sgqlc.types.Field(sgqlc.types.non_null(ReturnReason), graphql_name="returnReason") + return_reason_note = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="returnReasonNote") + total_weight = sgqlc.types.Field(Weight, graphql_name="totalWeight") + with_code_discounted_total_price_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="withCodeDiscountedTotalPriceSet") + + +class ReturnUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ReturnErrorCode, graphql_name="code") + + +class ReturnableFulfillment(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("fulfillment", "returnable_fulfillment_line_items") + fulfillment = sgqlc.types.Field(sgqlc.types.non_null(Fulfillment), graphql_name="fulfillment") + returnable_fulfillment_line_items = sgqlc.types.Field( + sgqlc.types.non_null(ReturnableFulfillmentLineItemConnection), + graphql_name="returnableFulfillmentLineItems", args=sgqlc.types.ArgDict( ( ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -23769,9 +27827,15 @@ class Publication(sgqlc.types.Type, Node): ) ), ) - products = sgqlc.types.Field( - sgqlc.types.non_null(ProductConnection), - graphql_name="products", + + +class ReverseDelivery(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("deliverable", "reverse_delivery_line_items", "reverse_fulfillment_order") + deliverable = sgqlc.types.Field("ReverseDeliveryDeliverable", graphql_name="deliverable") + reverse_delivery_line_items = sgqlc.types.Field( + sgqlc.types.non_null(ReverseDeliveryLineItemConnection), + graphql_name="reverseDeliveryLineItems", args=sgqlc.types.ArgDict( ( ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -23782,29 +27846,27 @@ class Publication(sgqlc.types.Type, Node): ) ), ) - supports_future_publishing = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="supportsFuturePublishing") + reverse_fulfillment_order = sgqlc.types.Field(sgqlc.types.non_null("ReverseFulfillmentOrder"), graphql_name="reverseFulfillmentOrder") -class Refund(sgqlc.types.Type, LegacyInteroperability, Node): +class ReverseDeliveryLineItem(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "created_at", - "duties", - "note", - "order", - "refund_line_items", - "staff_member", - "total_refunded_set", - "transactions", - "updated_at", + __field_names__ = ("dispositions", "quantity", "reverse_fulfillment_order_line_item") + dispositions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ReverseFulfillmentOrderDisposition"))), graphql_name="dispositions" ) - created_at = sgqlc.types.Field(DateTime, graphql_name="createdAt") - duties = sgqlc.types.Field(sgqlc.types.list_of(sgqlc.types.non_null(RefundDuty)), graphql_name="duties") - note = sgqlc.types.Field(String, graphql_name="note") - order = sgqlc.types.Field(sgqlc.types.non_null(Order), graphql_name="order") - refund_line_items = sgqlc.types.Field( - sgqlc.types.non_null(RefundLineItemConnection), - graphql_name="refundLineItems", + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + reverse_fulfillment_order_line_item = sgqlc.types.Field( + sgqlc.types.non_null("ReverseFulfillmentOrderLineItem"), graphql_name="reverseFulfillmentOrderLineItem" + ) + + +class ReverseFulfillmentOrder(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("line_items", "order", "reverse_deliveries", "status", "third_party_confirmation") + line_items = sgqlc.types.Field( + sgqlc.types.non_null(ReverseFulfillmentOrderLineItemConnection), + graphql_name="lineItems", args=sgqlc.types.ArgDict( ( ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -23815,11 +27877,10 @@ class Refund(sgqlc.types.Type, LegacyInteroperability, Node): ) ), ) - staff_member = sgqlc.types.Field("StaffMember", graphql_name="staffMember") - total_refunded_set = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="totalRefundedSet") - transactions = sgqlc.types.Field( - sgqlc.types.non_null(OrderTransactionConnection), - graphql_name="transactions", + order = sgqlc.types.Field(sgqlc.types.non_null(Order), graphql_name="order") + reverse_deliveries = sgqlc.types.Field( + sgqlc.types.non_null(ReverseDeliveryConnection), + graphql_name="reverseDeliveries", args=sgqlc.types.ArgDict( ( ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), @@ -23830,13 +27891,34 @@ class Refund(sgqlc.types.Type, LegacyInteroperability, Node): ) ), ) - updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") + status = sgqlc.types.Field(sgqlc.types.non_null(ReverseFulfillmentOrderStatus), graphql_name="status") + third_party_confirmation = sgqlc.types.Field(ReverseFulfillmentOrderThirdPartyConfirmation, graphql_name="thirdPartyConfirmation") -class RefundAgreement(sgqlc.types.Type, SalesAgreement): +class ReverseFulfillmentOrderDisposition(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ("refund",) - refund = sgqlc.types.Field(sgqlc.types.non_null(Refund), graphql_name="refund") + __field_names__ = ("location", "quantity", "type") + location = sgqlc.types.Field(Location, graphql_name="location") + quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="quantity") + type = sgqlc.types.Field(sgqlc.types.non_null(ReverseFulfillmentOrderDispositionType), graphql_name="type") + + +class ReverseFulfillmentOrderLineItem(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("dispositions", "fulfillment_line_item", "total_quantity") + dispositions = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ReverseFulfillmentOrderDisposition))), graphql_name="dispositions" + ) + fulfillment_line_item = sgqlc.types.Field(sgqlc.types.non_null(FulfillmentLineItem), graphql_name="fulfillmentLineItem") + total_quantity = sgqlc.types.Field(sgqlc.types.non_null(Int), graphql_name="totalQuantity") + + +class SaleAdditionalFee(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("name", "price", "tax_lines") + name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") + price = sgqlc.types.Field(sgqlc.types.non_null(MoneyBag), graphql_name="price") + tax_lines = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(TaxLine))), graphql_name="taxLines") class SavedSearch(sgqlc.types.Type, LegacyInteroperability, Node): @@ -23876,19 +27958,7 @@ class Segment(sgqlc.types.Type, Node): class SegmentAssociationFilter(sgqlc.types.Type, SegmentFilter): __schema__ = shopify_schema - __field_names__ = ("values",) - values = sgqlc.types.Field( - sgqlc.types.non_null(SegmentAssociationFilterValueConnection), - graphql_name="values", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ) - ), - ) + __field_names__ = () class SegmentBooleanFilter(sgqlc.types.Type, SegmentFilter): @@ -23903,41 +27973,16 @@ class SegmentDateFilter(sgqlc.types.Type, SegmentFilter): class SegmentEnumFilter(sgqlc.types.Type, SegmentFilter): __schema__ = shopify_schema - __field_names__ = ("values",) - values = sgqlc.types.Field( - sgqlc.types.non_null(SegmentEnumFilterValueConnection), - graphql_name="values", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ) - ), - ) + __field_names__ = () class SegmentEventFilter(sgqlc.types.Type, SegmentFilter): __schema__ = shopify_schema - __field_names__ = ("parameters", "return_value_type", "values") + __field_names__ = ("parameters", "return_value_type") parameters = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentEventFilterParameter))), - graphql_name="parameters", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(SegmentEventFilterParameter))), graphql_name="parameters" ) return_value_type = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="returnValueType") - values = sgqlc.types.Field( - sgqlc.types.non_null(SegmentEventFilterValueConnection), - graphql_name="values", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ) - ), - ) class SegmentFloatFilter(sgqlc.types.Type, SegmentFilter): @@ -23952,22 +27997,10 @@ class SegmentIntegerFilter(sgqlc.types.Type, SegmentFilter): class SegmentStringFilter(sgqlc.types.Type, SegmentFilter): __schema__ = shopify_schema - __field_names__ = ("values",) - values = sgqlc.types.Field( - sgqlc.types.non_null(SegmentStringFilterValueConnection), - graphql_name="values", - args=sgqlc.types.ArgDict( - ( - ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), - ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), - ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), - ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), - ) - ), - ) + __field_names__ = () -class SellingPlan(sgqlc.types.Type, Node): +class SellingPlan(sgqlc.types.Type, HasPublishedTranslations, Node): __schema__ = shopify_schema __field_names__ = ( "billing_policy", @@ -23991,8 +28024,7 @@ class SellingPlan(sgqlc.types.Type, Node): options = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="options") position = sgqlc.types.Field(Int, graphql_name="position") pricing_policies = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanPricingPolicy"))), - graphql_name="pricingPolicies", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("SellingPlanPricingPolicy"))), graphql_name="pricingPolicies" ) @@ -24002,7 +28034,7 @@ class SellingPlanFixedPricingPolicy(sgqlc.types.Type, SellingPlanPricingPolicyBa created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") -class SellingPlanGroup(sgqlc.types.Type, Node): +class SellingPlanGroup(sgqlc.types.Type, HasPublishedTranslations, Node): __schema__ = shopify_schema __field_names__ = ( "app_id", @@ -24032,12 +28064,7 @@ class SellingPlanGroup(sgqlc.types.Type, Node): sgqlc.types.non_null(Boolean), graphql_name="appliesToProductVariant", args=sgqlc.types.ArgDict( - ( - ( - "product_variant_id", - sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productVariantId", default=None), - ), - ) + (("product_variant_id", sgqlc.types.Arg(sgqlc.types.non_null(ID), graphql_name="productVariantId", default=None)),) ), ) applies_to_product_variants = sgqlc.types.Field( @@ -24113,6 +28140,13 @@ class SellingPlanRecurringPricingPolicy(sgqlc.types.Type, SellingPlanPricingPoli created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") +class ServerPixel(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ("status", "webhook_endpoint_address") + status = sgqlc.types.Field(ServerPixelStatus, graphql_name="status") + webhook_endpoint_address = sgqlc.types.Field(String, graphql_name="webhookEndpointAddress") + + class ShippingLineSale(sgqlc.types.Type, Sale): __schema__ = shopify_schema __field_names__ = ("shipping_line",) @@ -24181,22 +28215,15 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): ) alerts = sgqlc.types.Field(sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ShopAlert))), graphql_name="alerts") all_product_categories = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductCategory))), - graphql_name="allProductCategories", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ProductCategory))), graphql_name="allProductCategories" ) assigned_fulfillment_orders = sgqlc.types.Field( sgqlc.types.non_null(FulfillmentOrderConnection), graphql_name="assignedFulfillmentOrders", args=sgqlc.types.ArgDict( ( - ( - "assignment_status", - sgqlc.types.Arg(FulfillmentOrderAssignmentStatus, graphql_name="assignmentStatus", default=None), - ), - ( - "location_ids", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationIds", default=None), - ), + ("assignment_status", sgqlc.types.Arg(FulfillmentOrderAssignmentStatus, graphql_name="assignmentStatus", default=None)), + ("location_ids", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(ID)), graphql_name="locationIds", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -24219,7 +28246,7 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): ) ), ) - billing_address = sgqlc.types.Field(sgqlc.types.non_null(MailingAddress), graphql_name="billingAddress") + billing_address = sgqlc.types.Field(sgqlc.types.non_null("ShopAddress"), graphql_name="billingAddress") channel_definitions_for_installed_channels = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(AvailableChannelDefinitionsByChannel))), graphql_name="channelDefinitionsForInstalledChannels", @@ -24256,13 +28283,11 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): ) email = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="email") enabled_presentment_currencies = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CurrencyCode))), - graphql_name="enabledPresentmentCurrencies", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(CurrencyCode))), graphql_name="enabledPresentmentCurrencies" ) features = sgqlc.types.Field(sgqlc.types.non_null(ShopFeatures), graphql_name="features") fulfillment_services = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentService))), - graphql_name="fulfillmentServices", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(FulfillmentService))), graphql_name="fulfillmentServices" ) iana_timezone = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="ianaTimezone") limited_pending_order_count = sgqlc.types.Field(sgqlc.types.non_null(LimitedPendingOrderCount), graphql_name="limitedPendingOrderCount") @@ -24270,8 +28295,7 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): myshopify_domain = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="myshopifyDomain") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") navigation_settings = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(NavigationItem))), - graphql_name="navigationSettings", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(NavigationItem))), graphql_name="navigationSettings" ) order_number_format_prefix = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="orderNumberFormatPrefix") order_number_format_suffix = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="orderNumberFormatSuffix") @@ -24326,10 +28350,7 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): args=sgqlc.types.ArgDict( ( ("query", sgqlc.types.Arg(sgqlc.types.non_null(String), graphql_name="query", default=None)), - ( - "types", - sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(SearchResultType)), graphql_name="types", default=None), - ), + ("types", sgqlc.types.Arg(sgqlc.types.list_of(sgqlc.types.non_null(SearchResultType)), graphql_name="types", default=None)), ("first", sgqlc.types.Arg(sgqlc.types.non_null(Int), graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ) @@ -24384,9 +28405,7 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): ( "image_ids", sgqlc.types.Arg( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), - graphql_name="imageIds", - default=None, + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(ID))), graphql_name="imageIds", default=None ), ), ) @@ -24396,6 +28415,46 @@ class Shop(sgqlc.types.Type, HasMetafields, HasPublishedTranslations, Node): weight_unit = sgqlc.types.Field(sgqlc.types.non_null(WeightUnit), graphql_name="weightUnit") +class ShopAddress(sgqlc.types.Type, Node): + __schema__ = shopify_schema + __field_names__ = ( + "address1", + "address2", + "city", + "company", + "coordinates_validated", + "country", + "country_code_v2", + "formatted", + "formatted_area", + "latitude", + "longitude", + "phone", + "province", + "province_code", + "zip", + ) + address1 = sgqlc.types.Field(String, graphql_name="address1") + address2 = sgqlc.types.Field(String, graphql_name="address2") + city = sgqlc.types.Field(String, graphql_name="city") + company = sgqlc.types.Field(String, graphql_name="company") + coordinates_validated = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="coordinatesValidated") + country = sgqlc.types.Field(String, graphql_name="country") + country_code_v2 = sgqlc.types.Field(CountryCode, graphql_name="countryCodeV2") + formatted = sgqlc.types.Field( + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), + graphql_name="formatted", + args=sgqlc.types.ArgDict((("with_company", sgqlc.types.Arg(Boolean, graphql_name="withCompany", default=True)),)), + ) + formatted_area = sgqlc.types.Field(String, graphql_name="formattedArea") + latitude = sgqlc.types.Field(Float, graphql_name="latitude") + longitude = sgqlc.types.Field(Float, graphql_name="longitude") + phone = sgqlc.types.Field(String, graphql_name="phone") + province = sgqlc.types.Field(String, graphql_name="province") + province_code = sgqlc.types.Field(String, graphql_name="provinceCode") + zip = sgqlc.types.Field(String, graphql_name="zip") + + class ShopPolicy(sgqlc.types.Type, HasPublishedTranslations, Node): __schema__ = shopify_schema __field_names__ = ("body", "type", "url") @@ -24410,6 +28469,12 @@ class ShopPolicyUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(ShopPolicyErrorCode, graphql_name="code") +class ShopResourceFeedbackCreateUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(ShopResourceFeedbackCreateUserErrorCode, graphql_name="code") + + class ShopifyPaymentsAccount(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ( @@ -24473,10 +28538,7 @@ class ShopifyPaymentsAccount(sgqlc.types.Type, Node): graphql_name="payouts", args=sgqlc.types.ArgDict( ( - ( - "transaction_type", - sgqlc.types.Arg(ShopifyPaymentsPayoutTransactionType, graphql_name="transactionType", default=None), - ), + ("transaction_type", sgqlc.types.Arg(ShopifyPaymentsPayoutTransactionType, graphql_name="transactionType", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -24490,8 +28552,7 @@ class ShopifyPaymentsAccount(sgqlc.types.Type, Node): graphql_name="permittedVerificationDocuments", ) verifications = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsVerification"))), - graphql_name="verifications", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsVerification"))), graphql_name="verifications" ) @@ -24519,10 +28580,7 @@ class ShopifyPaymentsBankAccount(sgqlc.types.Type, Node): graphql_name="payouts", args=sgqlc.types.ArgDict( ( - ( - "transaction_type", - sgqlc.types.Arg(ShopifyPaymentsPayoutTransactionType, graphql_name="transactionType", default=None), - ), + ("transaction_type", sgqlc.types.Arg(ShopifyPaymentsPayoutTransactionType, graphql_name="transactionType", default=None)), ("first", sgqlc.types.Arg(Int, graphql_name="first", default=None)), ("after", sgqlc.types.Arg(String, graphql_name="after", default=None)), ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), @@ -24607,8 +28665,7 @@ class ShopifyPaymentsDisputeEvidence(sgqlc.types.Type, Node): graphql_name="disputeFileUploads", ) fulfillments = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsDisputeFulfillment"))), - graphql_name="fulfillments", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null("ShopifyPaymentsDisputeFulfillment"))), graphql_name="fulfillments" ) product_description = sgqlc.types.Field(String, graphql_name="productDescription") refund_policy_disclosure = sgqlc.types.Field(String, graphql_name="refundPolicyDisclosure") @@ -24707,16 +28764,7 @@ class StandardMetafieldDefinitionEnableUserError(sgqlc.types.Type, DisplayableEr class StandardMetafieldDefinitionTemplate(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "description", - "key", - "name", - "namespace", - "owner_types", - "type", - "validations", - "visible_to_storefront_api", - ) + __field_names__ = ("description", "key", "name", "namespace", "owner_types", "type", "validations", "visible_to_storefront_api") description = sgqlc.types.Field(String, graphql_name="description") key = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="key") name = sgqlc.types.Field(sgqlc.types.non_null(String), graphql_name="name") @@ -24726,8 +28774,7 @@ class StandardMetafieldDefinitionTemplate(sgqlc.types.Type, Node): ) type = sgqlc.types.Field(sgqlc.types.non_null(MetafieldDefinitionType), graphql_name="type") validations = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidation))), - graphql_name="validations", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(MetafieldDefinitionValidation))), graphql_name="validations" ) visible_to_storefront_api = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="visibleToStorefrontApi") @@ -24783,10 +28830,7 @@ class SubscriptionBillingCycleEditedContract(sgqlc.types.Type, SubscriptionContr ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX"), - ), + ("sort_key", sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX")), ) ), ) @@ -24809,6 +28853,7 @@ class SubscriptionContract(sgqlc.types.Type, Node, SubscriptionContractBase): "last_payment_status", "next_billing_date", "origin_order", + "revision_id", "status", ) billing_attempts = sgqlc.types.Field( @@ -24830,6 +28875,7 @@ class SubscriptionContract(sgqlc.types.Type, Node, SubscriptionContractBase): last_payment_status = sgqlc.types.Field(SubscriptionContractLastPaymentStatus, graphql_name="lastPaymentStatus") next_billing_date = sgqlc.types.Field(DateTime, graphql_name="nextBillingDate") origin_order = sgqlc.types.Field(Order, graphql_name="originOrder") + revision_id = sgqlc.types.Field(sgqlc.types.non_null(UnsignedInt64), graphql_name="revisionId") status = sgqlc.types.Field(sgqlc.types.non_null(SubscriptionContractSubscriptionStatus), graphql_name="status") @@ -24877,10 +28923,7 @@ class SubscriptionDraft(sgqlc.types.Type, Node): ("last", sgqlc.types.Arg(Int, graphql_name="last", default=None)), ("before", sgqlc.types.Arg(String, graphql_name="before", default=None)), ("reverse", sgqlc.types.Arg(Boolean, graphql_name="reverse", default=False)), - ( - "sort_key", - sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX"), - ), + ("sort_key", sgqlc.types.Arg(SubscriptionBillingCyclesSortKeys, graphql_name="sortKey", default="CYCLE_INDEX")), ) ), ) @@ -25007,17 +29050,20 @@ class SubscriptionDraftUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(SubscriptionDraftErrorCode, graphql_name="code") +class TableResponse(sgqlc.types.Type, ShopifyqlResponse): + __schema__ = shopify_schema + __field_names__ = () + + +class TaxAppConfigureUserError(sgqlc.types.Type, DisplayableError): + __schema__ = shopify_schema + __field_names__ = ("code",) + code = sgqlc.types.Field(TaxAppConfigureUserErrorCode, graphql_name="code") + + class TenderTransaction(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "amount", - "payment_method", - "processed_at", - "remote_reference", - "test", - "transaction_details", - "user", - ) + __field_names__ = ("amount", "payment_method", "processed_at", "remote_reference", "test", "transaction_details", "user") amount = sgqlc.types.Field(sgqlc.types.non_null(MoneyV2), graphql_name="amount") payment_method = sgqlc.types.Field(String, graphql_name="paymentMethod") processed_at = sgqlc.types.Field(DateTime, graphql_name="processedAt") @@ -25051,6 +29097,11 @@ class TranslationUserError(sgqlc.types.Type, DisplayableError): code = sgqlc.types.Field(TranslationErrorCode, graphql_name="code") +class UnknownSale(sgqlc.types.Type, Sale): + __schema__ = shopify_schema + __field_names__ = () + + class UrlRedirect(sgqlc.types.Type, Node): __schema__ = shopify_schema __field_names__ = ("path", "target") @@ -25078,23 +29129,14 @@ class UrlRedirectBulkDeleteBySearchUserError(sgqlc.types.Type, DisplayableError) class UrlRedirectImport(sgqlc.types.Type, Node): __schema__ = shopify_schema - __field_names__ = ( - "count", - "created_count", - "failed_count", - "finished", - "finished_at", - "preview_redirects", - "updated_count", - ) + __field_names__ = ("count", "created_count", "failed_count", "finished", "finished_at", "preview_redirects", "updated_count") count = sgqlc.types.Field(Int, graphql_name="count") created_count = sgqlc.types.Field(Int, graphql_name="createdCount") failed_count = sgqlc.types.Field(Int, graphql_name="failedCount") finished = sgqlc.types.Field(sgqlc.types.non_null(Boolean), graphql_name="finished") finished_at = sgqlc.types.Field(DateTime, graphql_name="finishedAt") preview_redirects = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(UrlRedirectImportPreview))), - graphql_name="previewRedirects", + sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(UrlRedirectImportPreview))), graphql_name="previewRedirects" ) updated_count = sgqlc.types.Field(Int, graphql_name="updatedCount") @@ -25133,16 +29175,8 @@ class WebPixel(sgqlc.types.Type, Node): class WebhookSubscription(sgqlc.types.Type, LegacyInteroperability, Node): __schema__ = shopify_schema - __field_names__ = ( - "created_at", - "endpoint", - "format", - "include_fields", - "metafield_namespaces", - "private_metafield_namespaces", - "topic", - "updated_at", - ) + __field_names__ = ("api_version", "created_at", "endpoint", "format", "include_fields", "metafield_namespaces", "topic", "updated_at") + api_version = sgqlc.types.Field(sgqlc.types.non_null(ApiVersion), graphql_name="apiVersion") created_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="createdAt") endpoint = sgqlc.types.Field(sgqlc.types.non_null("WebhookSubscriptionEndpoint"), graphql_name="endpoint") format = sgqlc.types.Field(sgqlc.types.non_null(WebhookSubscriptionFormat), graphql_name="format") @@ -25152,10 +29186,6 @@ class WebhookSubscription(sgqlc.types.Type, LegacyInteroperability, Node): metafield_namespaces = sgqlc.types.Field( sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), graphql_name="metafieldNamespaces" ) - private_metafield_namespaces = sgqlc.types.Field( - sgqlc.types.non_null(sgqlc.types.list_of(sgqlc.types.non_null(String))), - graphql_name="privateMetafieldNamespaces", - ) topic = sgqlc.types.Field(sgqlc.types.non_null(WebhookSubscriptionTopic), graphql_name="topic") updated_at = sgqlc.types.Field(sgqlc.types.non_null(DateTime), graphql_name="updatedAt") @@ -25175,7 +29205,12 @@ class AppSubscriptionDiscountValue(sgqlc.types.Union): class CollectionRuleConditionObject(sgqlc.types.Union): __schema__ = shopify_schema - __types__ = (CollectionRuleProductCategoryCondition, CollectionRuleTextCondition) + __types__ = (CollectionRuleMetafieldCondition, CollectionRuleProductCategoryCondition, CollectionRuleTextCondition) + + +class CollectionRuleConditionsRuleObject(sgqlc.types.Union): + __schema__ = shopify_schema + __types__ = (CollectionRuleMetafieldCondition,) class CommentEventEmbed(sgqlc.types.Union): @@ -25258,7 +29293,33 @@ class DiscountShippingDestinationSelection(sgqlc.types.Union): class MetafieldReference(sgqlc.types.Union): __schema__ = shopify_schema - __types__ = (Collection, GenericFile, MediaImage, OnlineStorePage, Product, ProductVariant, Video) + __types__ = (Collection, GenericFile, MediaImage, Metaobject, OnlineStorePage, Product, ProductVariant, Video) + + +class MetafieldReferencer(sgqlc.types.Union): + __schema__ = shopify_schema + __types__ = ( + AppInstallation, + Collection, + Customer, + DeliveryCustomization, + DiscountAutomaticNode, + DiscountCodeNode, + DiscountNode, + DraftOrder, + FulfillmentOrder, + Location, + Market, + Metaobject, + OnlineStoreArticle, + OnlineStoreBlog, + OnlineStorePage, + Order, + PaymentCustomization, + Product, + ProductVariant, + Shop, + ) class OrderStagedChange(sgqlc.types.Union): @@ -25273,6 +29334,11 @@ class OrderStagedChange(sgqlc.types.Union): ) +class PaymentDetails(sgqlc.types.Union): + __schema__ = shopify_schema + __types__ = (CardPaymentDetails,) + + class PaymentInstrument(sgqlc.types.Union): __schema__ = shopify_schema __types__ = (VaultCreditCard, VaultPaypalBillingAgreement) @@ -25288,11 +29354,21 @@ class PricingValue(sgqlc.types.Union): __types__ = (MoneyV2, PricingPercentageValue) +class PublicationOperation(sgqlc.types.Union): + __schema__ = shopify_schema + __types__ = (AddAllProductsOperation, CatalogCsvOperation, PublicationResourceOperation) + + class PurchasingEntity(sgqlc.types.Union): __schema__ = shopify_schema __types__ = (Customer, PurchasingCompany) +class ReverseDeliveryDeliverable(sgqlc.types.Union): + __schema__ = shopify_schema + __types__ = (ReverseDeliveryShippingDeliverable,) + + class SellingPlanBillingPolicy(sgqlc.types.Union): __schema__ = shopify_schema __types__ = (SellingPlanFixedBillingPolicy, SellingPlanRecurringBillingPolicy) @@ -25320,11 +29396,7 @@ class SellingPlanPricingPolicyAdjustmentValue(sgqlc.types.Union): class SubscriptionDeliveryMethod(sgqlc.types.Union): __schema__ = shopify_schema - __types__ = ( - SubscriptionDeliveryMethodLocalDelivery, - SubscriptionDeliveryMethodPickup, - SubscriptionDeliveryMethodShipping, - ) + __types__ = (SubscriptionDeliveryMethodLocalDelivery, SubscriptionDeliveryMethodPickup, SubscriptionDeliveryMethodShipping) class SubscriptionDeliveryOption(sgqlc.types.Union): diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/source.py b/airbyte-integrations/connectors/source-shopify/source_shopify/source.py index 8225aa5f08c6..7c584865f1c0 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/source.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/source.py @@ -3,932 +3,68 @@ # -import logging -from abc import ABC, abstractmethod -from functools import cached_property -from typing import Any, Dict, Iterable, List, Mapping, MutableMapping, Optional, Tuple, Union -from urllib.parse import parse_qsl, urlparse +from typing import Any, List, Mapping, Tuple -import requests from airbyte_cdk import AirbyteLogger +from airbyte_cdk.models import SyncMode from airbyte_cdk.sources import AbstractSource from airbyte_cdk.sources.streams import Stream -from airbyte_cdk.sources.streams.http import HttpStream -from requests.exceptions import ConnectionError, InvalidURL, JSONDecodeError, RequestException, SSLError +from requests.exceptions import ConnectionError, RequestException, SSLError from .auth import MissingAccessTokenError, ShopifyAuthenticator -from .graphql import get_query_products -from .transform import DataTypeEnforcer -from .utils import SCOPES_MAPPING, ApiTypeEnum -from .utils import EagerlyCachedStreamState as stream_state_cache -from .utils import ShopifyAccessScopesError, ShopifyBadJsonError, ShopifyConnectionError, ShopifyNonRetryableErrors -from .utils import ShopifyRateLimiter as limiter -from .utils import ShopifyWrongShopNameError - - -class ShopifyStream(HttpStream, ABC): - - # define default logger - logger = logging.getLogger("airbyte") - - # Latest Stable Release - api_version = "2023-07" - # Page size - limit = 250 - - primary_key = "id" - order_field = "updated_at" - filter_field = "updated_at_min" - - raise_on_http_errors = True - max_retries = 5 - - def __init__(self, config: Dict): - super().__init__(authenticator=config["authenticator"]) - self._transformer = DataTypeEnforcer(self.get_json_schema()) - self.config = config - - @property - @abstractmethod - def data_field(self) -> str: - """The name of the field in the response which contains the data""" - - @property - def url_base(self) -> str: - return f"https://{self.config['shop']}.myshopify.com/admin/api/{self.api_version}/" - - @property - def default_filter_field_value(self) -> Union[int, str]: - # certain streams are using `since_id` field as `filter_field`, which requires to use `int` type, - # but many other use `str` values for this, we determine what to use based on `filter_field` value - # by default, we use the user defined `Start Date` as initial value, or 0 for `id`-dependent streams. - return 0 if self.filter_field == "since_id" else (self.config.get("start_date") or "") - - def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: - next_page = response.links.get("next", None) - if next_page: - return dict(parse_qsl(urlparse(next_page.get("url")).query)) - else: - return None - - def request_params(self, next_page_token: Mapping[str, Any] = None, **kwargs) -> MutableMapping[str, Any]: - params = {"limit": self.limit} - if next_page_token: - params.update(**next_page_token) - else: - params["order"] = f"{self.order_field} asc" - params[self.filter_field] = self.default_filter_field_value - if self.config.get("end_date") and self.filter_field == "updated_at_min": - params["updated_at_max"] = self.config.get("end_date") - return params - - @limiter.balance_rate_limit() - def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: - if response.status_code is requests.codes.OK: - try: - json_response = response.json() - records = json_response.get(self.data_field, []) if self.data_field is not None else json_response - yield from self.produce_records(records) - except RequestException as e: - self.logger.warning(f"Unexpected error in `parse_ersponse`: {e}, the actual response data: {response.text}") - yield {} - - def produce_records(self, records: Union[Iterable[Mapping[str, Any]], Mapping[str, Any]] = None) -> Iterable[Mapping[str, Any]]: - # transform method was implemented according to issue 4841 - # Shopify API returns price fields as a string and it should be converted to number - # this solution designed to convert string into number, but in future can be modified for general purpose - if isinstance(records, dict): - # for cases when we have a single record as dict - # add shop_url to the record to make querying easy - records["shop_url"] = self.config["shop"] - yield self._transformer.transform(records) - else: - # for other cases - for record in records: - # add shop_url to the record to make querying easy - record["shop_url"] = self.config["shop"] - yield self._transformer.transform(record) - - def should_retry(self, response: requests.Response) -> bool: - known_errors = ShopifyNonRetryableErrors(self.name) - status = response.status_code - if status in known_errors.keys(): - setattr(self, "raise_on_http_errors", False) - self.logger.warning(known_errors.get(status)) - return False - else: - return super().should_retry(response) - - -class ShopifyDeletedEventsStream(ShopifyStream): - - data_field = "events" - primary_key = "id" - cursor_field = "deleted_at" - - @property - def availability_strategy(self) -> None: - """ - No need to apply the `availability strategy` for this service stream. - """ - return None - - def __init__(self, config: Dict, deleted_events_api_name: str): - self.deleted_events_api_name = deleted_events_api_name - super().__init__(config) - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - def get_json_schema(self) -> None: - """ - No need to apply the `schema` for this service stream. - """ - return {} - - def produce_deleted_records_from_events(self, delete_events: Iterable[Mapping[str, Any]] = []) -> None: - for event in delete_events: - yield { - "id": event["subject_id"], - self.cursor_field: event["created_at"], - "updated_at": event["created_at"], - "deleted_message": event["message"], - "deleted_description": event["description"], - "shop_url": event["shop_url"], - } - - def read_records(self, stream_state: Mapping[str, Any] = None, **kwargs): - delete_events = super().read_records(stream_state=stream_state, **kwargs) - yield from self.produce_deleted_records_from_events(delete_events) - - def request_params( - self, - stream_state: Mapping[str, Any] = None, - next_page_token: Mapping[str, Any] = None, - **kwargs, - ) -> Mapping[str, Any]: - params = {} - - if not next_page_token: - params.update(**{"filter": self.deleted_events_api_name, "verb": "destroy"}) - if stream_state: - state = stream_state.get("deleted", {}).get(self.cursor_field) - if state: - params["created_at_min"] = state - else: - # `filter` and `verb` cannot be passed, when `page_info` is present. - # See https://shopify.dev/api/usage/pagination-rest - params.update(**next_page_token) - - return params - - -class IncrementalShopifyStream(ShopifyStream, ABC): - - # Setting the check point interval to the limit of the records output - @property - def state_checkpoint_interval(self) -> int: - return super().limit - - # Setting the default cursor field for all streams - cursor_field = "updated_at" - deleted_cursor_field = "deleted_at" - - @property - def default_state_comparison_value(self) -> Union[int, str]: - # certain streams are using `id` field as `cursor_field`, which requires to use `int` type, - # but many other use `str` values for this, we determine what to use based on `cursor_field` value - return 0 if self.cursor_field == "id" else "" - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - last_record_value = latest_record.get(self.cursor_field) or self.default_state_comparison_value - current_state_value = current_stream_state.get(self.cursor_field) or self.default_state_comparison_value - return {self.cursor_field: max(last_record_value, current_state_value)} - - @stream_state_cache.cache_stream_state - def request_params(self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs): - params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) - # If there is a next page token then we should only send pagination-related parameters. - if not next_page_token: - params["order"] = f"{self.order_field} asc" - if stream_state: - params[self.filter_field] = stream_state.get(self.cursor_field) - return params - - # Parse the `stream_slice` with respect to `stream_state` for `Incremental refresh` - # cases where we slice the stream, the endpoints for those classes don't accept any other filtering, - # but they provide us with the updated_at field in most cases, so we used that as incremental filtering during the order slicing. - def filter_records_newer_than_state(self, stream_state: Mapping[str, Any] = None, records_slice: Iterable[Mapping] = None) -> Iterable: - # Getting records >= state - if stream_state: - state_value = stream_state.get(self.cursor_field) - for record in records_slice: - if self.cursor_field in record: - record_value = record.get(self.cursor_field, self.default_state_comparison_value) - if record_value: - if record_value >= state_value: - yield record - else: - # old entities could have cursor field in place, but set to null - self.logger.warning( - f"Stream `{self.name}`, Record ID: `{record.get(self.primary_key)}` cursor value is: {record_value}, record is emitted without state comparison" - ) - yield record - else: - # old entities could miss the cursor field - self.logger.warning( - f"Stream `{self.name}`, Record ID: `{record.get(self.primary_key)}` missing cursor field: {self.cursor_field}, record is emitted without state comparison" - ) - yield record - else: - yield from records_slice - - -class IncrementalShopifyStreamWithDeletedEvents(IncrementalShopifyStream): - @property - @abstractmethod - def deleted_events_api_name(self) -> str: - """ - The string value of the Shopify Events Object to pull: - - articles -> Article - blogs -> Blog - custom_collections -> Collection - orders -> Order - pages -> Page - price_rules -> PriceRule - products -> Product - - """ - - @property - def deleted_events(self) -> ShopifyDeletedEventsStream: - """ - The Events stream instance to fetch the `destroyed` records for specified `deleted_events_api_name`, like: `Product`. - See more in `ShopifyDeletedEventsStream` class. - """ - return ShopifyDeletedEventsStream(self.config, self.deleted_events_api_name) - - @property - def default_deleted_state_comparison_value(self) -> Union[int, str]: - """ - Set the default STATE comparison value for cases when the deleted record doesn't have it's value. - We expect the `deleted_at` cursor field for destroyed records would be always type of String. - """ - return "" - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - """ - We extend the stream state with `deleted` property to store the `destroyed` records STATE separetely from the Stream State. - """ - state = super().get_updated_state(current_stream_state, latest_record) - # add `deleted` property to each stream supports `deleted events`, - # to povide the `Incremental` sync mode, for the `Incremental Delete` records. - last_deleted_record_value = latest_record.get(self.deleted_cursor_field) or self.default_deleted_state_comparison_value - current_deleted_state_value = current_stream_state.get(self.deleted_cursor_field) or self.default_deleted_state_comparison_value - state["deleted"] = {self.deleted_cursor_field: max(last_deleted_record_value, current_deleted_state_value)} - return state - - def read_records( - self, - stream_state: Mapping[str, Any] = None, - stream_slice: Optional[Mapping[str, Any]] = None, - **kwargs, - ) -> Iterable[Mapping[str, Any]]: - """Override to fetch deleted records for supported streams""" - # main records stream - yield from super().read_records(stream_state=stream_state, stream_slice=stream_slice, **kwargs) - # fetch deleted events after the Stream data is pulled - yield from self.deleted_events.read_records(stream_state=stream_state, **kwargs) - - -class ShopifySubstream(IncrementalShopifyStream): - """ - ShopifySubstream - provides slicing functionality for streams using parts of data from parent stream. - For example: - - `Refunds Orders` is the entity of `Orders`, - - `OrdersRisks` is the entity of `Orders`, - - `DiscountCodes` is the entity of `PriceRules`, etc. - - :: @ parent_stream - defines the parent stream object to read from - :: @ slice_key - defines the name of the property in stream slices dict. - :: @ nested_record - the name of the field inside of parent stream record. Default is `id`. - :: @ nested_record_field_name - the name of the field inside of nested_record. - :: @ nested_substream - the name of the nested entity inside of parent stream, helps to reduce the number of - API Calls, if present, see `OrderRefunds` stream for more. - """ - - parent_stream_class: object = None - slice_key: str = None - nested_record: str = "id" - nested_record_field_name: str = None - nested_substream = None - nested_substream_list_field_id = None - - @cached_property - def parent_stream(self) -> object: - """ - Returns the instance of parent stream, if the substream has a `parent_stream_class` dependency. - """ - return self.parent_stream_class(self.config) if self.parent_stream_class else None - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - """UPDATING THE STATE OBJECT: - Stream: Transactions - Parent Stream: Orders - Returns: - { - {...}, - "transactions": { - "created_at": "2022-03-03T03:47:45-08:00", - "orders": { - "updated_at": "2022-03-03T03:47:46-08:00" - } - }, - {...}, - } - """ - updated_state = super().get_updated_state(current_stream_state, latest_record) - # add parent_stream_state to `updated_state` - updated_state[self.parent_stream.name] = stream_state_cache.cached_state.get(self.parent_stream.name) - return updated_state - - def request_params(self, next_page_token: Mapping[str, Any] = None, **kwargs) -> MutableMapping[str, Any]: - params = {"limit": self.limit} - if next_page_token: - params.update(**next_page_token) - return params - - def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: - """ - Reading the parent stream for slices with structure: - EXAMPLE: for given nested_record as `id` of Orders, - - Outputs: - [ - {slice_key: 123}, - {slice_key: 456}, - {...}, - {slice_key: 999 - ] - """ - sorted_substream_slices = [] - - # reading parent nested stream_state from child stream state - parent_stream_state = stream_state.get(self.parent_stream.name) if stream_state else {} - - # reading the parent stream - for record in self.parent_stream.read_records(stream_state=parent_stream_state, **kwargs): - # updating the `stream_state` with the state of it's parent stream - # to have the child stream sync independently from the parent stream - stream_state_cache.cached_state[self.parent_stream.name] = self.parent_stream.get_updated_state({}, record) - # to limit the number of API Calls and reduce the time of data fetch, - # we can pull the ready data for child_substream, if nested data is present, - # and corresponds to the data of child_substream we need. - if self.nested_substream and self.nested_substream_list_field_id: - if record.get(self.nested_substream): - sorted_substream_slices.extend( - [ - { - self.slice_key: sub_record[self.nested_substream_list_field_id], - self.cursor_field: record[self.nested_substream][0].get( - self.cursor_field, self.default_state_comparison_value - ), - } - for sub_record in record[self.nested_record] - ] - ) - elif self.nested_substream: - if record.get(self.nested_substream): - sorted_substream_slices.append( - { - self.slice_key: record[self.nested_record], - self.cursor_field: record[self.nested_substream][0].get(self.cursor_field, self.default_state_comparison_value), - } - ) - else: - # avoid checking `deleted` records for substreams, a.k.a `Metafields` streams, - # since `deleted` records are not available, thus we avoid HTTP-400 errors. - if self.deleted_cursor_field not in record: - yield {self.slice_key: record[self.nested_record]} - - # output slice from sorted list to avoid filtering older records - if self.nested_substream: - if len(sorted_substream_slices) > 0: - # sort by cursor_field - sorted_substream_slices.sort(key=lambda x: x.get(self.cursor_field)) - for sorted_slice in sorted_substream_slices: - yield {self.slice_key: sorted_slice[self.slice_key]} - - def read_records( - self, - stream_state: Mapping[str, Any] = None, - stream_slice: Optional[Mapping[str, Any]] = None, - **kwargs, - ) -> Iterable[Mapping[str, Any]]: - """Reading child streams records for each `id`""" - - slice_data = stream_slice.get(self.slice_key) - # sometimes the stream_slice.get(self.slice_key) has the list of records, - # to avoid data exposition inside the logs, we should get the data we need correctly out of stream_slice. - if isinstance(slice_data, list) and self.nested_record_field_name is not None and len(slice_data) > 0: - slice_data = slice_data[0].get(self.nested_record_field_name) - - self.logger.info(f"Reading {self.name} for {self.slice_key}: {slice_data}") - records = super().read_records(stream_slice=stream_slice, **kwargs) - yield from self.filter_records_newer_than_state(stream_state=stream_state, records_slice=records) - - -class MetafieldShopifySubstream(ShopifySubstream): - slice_key = "id" - data_field = "metafields" - - parent_stream_class: object = None - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - object_id = stream_slice[self.slice_key] - return f"{self.parent_stream_class.data_field}/{object_id}/{self.data_field}.json" - - -class Articles(IncrementalShopifyStreamWithDeletedEvents): - data_field = "articles" - cursor_field = "id" - order_field = "id" - filter_field = "since_id" - deleted_events_api_name = "Article" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldArticles(MetafieldShopifySubstream): - parent_stream_class: object = Articles - - -class Blogs(IncrementalShopifyStreamWithDeletedEvents): - cursor_field = "id" - order_field = "id" - data_field = "blogs" - filter_field = "since_id" - deleted_events_api_name = "Blog" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldBlogs(MetafieldShopifySubstream): - parent_stream_class: object = Blogs - - -class Customers(IncrementalShopifyStream): - data_field = "customers" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldCustomers(MetafieldShopifySubstream): - parent_stream_class: object = Customers - - -class Orders(IncrementalShopifyStreamWithDeletedEvents): - data_field = "orders" - deleted_events_api_name = "Order" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - def request_params( - self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs - ) -> MutableMapping[str, Any]: - params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) - if not next_page_token: - params["status"] = "any" - return params - - -class Disputes(IncrementalShopifyStream): - data_field = "disputes" - filter_field = "since_id" - cursor_field = "id" - order_field = "id" - - def path(self, **kwargs) -> str: - return f"shopify_payments/{self.data_field}.json" - - -class MetafieldOrders(MetafieldShopifySubstream): - parent_stream_class: object = Orders - - -class DraftOrders(IncrementalShopifyStream): - data_field = "draft_orders" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldDraftOrders(MetafieldShopifySubstream): - parent_stream_class: object = DraftOrders - - -class Products(IncrementalShopifyStreamWithDeletedEvents): - use_cache = True - data_field = "products" - deleted_events_api_name = "Product" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class ProductsGraphQl(IncrementalShopifyStream): - filter_field = "updatedAt" - cursor_field = "updatedAt" - data_field = "graphql" - http_method = "POST" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - def request_params( - self, - stream_state: Optional[Mapping[str, Any]] = None, - next_page_token: Optional[Mapping[str, Any]] = None, - **kwargs, - ) -> MutableMapping[str, Any]: - return {} - - def request_body_json( - self, - stream_state: Mapping[str, Any], - stream_slice: Optional[Mapping[str, Any]] = None, - next_page_token: Optional[Mapping[str, Any]] = None, - ) -> Optional[Mapping]: - state_value = stream_state.get(self.filter_field) - if state_value: - filter_value = state_value - else: - filter_value = self.default_filter_field_value - query = get_query_products( - first=self.limit, filter_field=self.filter_field, filter_value=filter_value, next_page_token=next_page_token - ) - return {"query": query} - - @staticmethod - def next_page_token(response: requests.Response) -> Optional[Mapping[str, Any]]: - page_info = response.json()["data"]["products"]["pageInfo"] - has_next_page = page_info["hasNextPage"] - if has_next_page: - return page_info["endCursor"] - else: - return None - - @limiter.balance_rate_limit(api_type=ApiTypeEnum.graphql.value) - def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: - if response.status_code is requests.codes.OK: - try: - json_response = response.json()["data"]["products"]["nodes"] - yield from self.produce_records(json_response) - except RequestException as e: - self.logger.warning(f"Unexpected error in `parse_ersponse`: {e}, the actual response data: {response.text}") - yield {} - - -class MetafieldProducts(MetafieldShopifySubstream): - parent_stream_class: object = Products - - -class ProductImages(ShopifySubstream): - parent_stream_class: object = Products - cursor_field = "id" - slice_key = "product_id" - data_field = "images" - nested_substream = "images" - filter_field = "since_id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - product_id = stream_slice[self.slice_key] - return f"products/{product_id}/{self.data_field}.json" - - -class MetafieldProductImages(MetafieldShopifySubstream): - parent_stream_class: object = Products - nested_record = "images" - slice_key = "images" - nested_substream = "images" - nested_substream_list_field_id = "id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - image_id = stream_slice[self.slice_key] - return f"product_images/{image_id}/{self.data_field}.json" - - -class ProductVariants(ShopifySubstream): - parent_stream_class: object = Products - cursor_field = "id" - slice_key = "product_id" - data_field = "variants" - nested_substream = "variants" - filter_field = "since_id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - product_id = stream_slice[self.slice_key] - return f"products/{product_id}/{self.data_field}.json" - - -class MetafieldProductVariants(MetafieldShopifySubstream): - parent_stream_class: object = Products - nested_record = "variants" - slice_key = "variants" - nested_substream = "variants" - nested_substream_list_field_id = "id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - variant_id = stream_slice[self.slice_key] - return f"variants/{variant_id}/{self.data_field}.json" - - -class AbandonedCheckouts(IncrementalShopifyStream): - data_field = "checkouts" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - def request_params( - self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs - ) -> MutableMapping[str, Any]: - params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) - # If there is a next page token then we should only send pagination-related parameters. - if not next_page_token: - params["status"] = "any" - return params - - -class CustomCollections(IncrementalShopifyStreamWithDeletedEvents): - data_field = "custom_collections" - deleted_events_api_name = "Collection" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class SmartCollections(IncrementalShopifyStream): - data_field = "smart_collections" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldSmartCollections(MetafieldShopifySubstream): - parent_stream_class: object = SmartCollections - - -class Collects(IncrementalShopifyStream): - """ - Collects stream does not support Incremental Refresh based on datetime fields, only `since_id` is supported: - https://shopify.dev/docs/admin-api/rest/reference/products/collect - - The Collect stream is the link between Products and Collections, if the Collection is created for Products, - the `collect` record is created, it's reasonable to Full Refresh all collects. As for Incremental refresh - - we would use the since_id specificaly for this stream. - """ - - data_field = "collects" - cursor_field = "id" - order_field = "id" - filter_field = "since_id" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class Collections(ShopifySubstream): - parent_stream_class: object = Collects - nested_record = "collection_id" - slice_key = "collection_id" - data_field = "collection" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - collection_id = stream_slice[self.slice_key] - return f"collections/{collection_id}.json" - - -class MetafieldCollections(MetafieldShopifySubstream): - parent_stream_class: object = Collects - slice_key = "collection_id" - nested_record = "collection_id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - object_id = stream_slice[self.slice_key] - return f"collections/{object_id}/{self.data_field}.json" - - -class BalanceTransactions(IncrementalShopifyStream): - - """ - PaymentsTransactions stream does not support Incremental Refresh based on datetime fields, only `since_id` is supported: - https://shopify.dev/api/admin-rest/2021-07/resources/transactions - """ - - data_field = "transactions" - cursor_field = "id" - order_field = "id" - filter_field = "since_id" - - def path(self, **kwargs) -> str: - return f"shopify_payments/balance/{self.data_field}.json" - - -class OrderRefunds(ShopifySubstream): - parent_stream_class: object = Orders - slice_key = "order_id" - data_field = "refunds" - cursor_field = "created_at" - # we pull out the records that we already know has the refunds data from Orders object - nested_substream = "refunds" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - order_id = stream_slice["order_id"] - return f"orders/{order_id}/{self.data_field}.json" - - -class OrderRisks(ShopifySubstream): - parent_stream_class: object = Orders - slice_key = "order_id" - data_field = "risks" - cursor_field = "id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - order_id = stream_slice["order_id"] - return f"orders/{order_id}/{self.data_field}.json" - - -class Transactions(ShopifySubstream): - parent_stream_class: object = Orders - slice_key = "order_id" - data_field = "transactions" - cursor_field = "created_at" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - order_id = stream_slice["order_id"] - return f"orders/{order_id}/{self.data_field}.json" - - -class TenderTransactions(IncrementalShopifyStream): - data_field = "tender_transactions" - cursor_field = "processed_at" - filter_field = "processed_at_min" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class Pages(IncrementalShopifyStreamWithDeletedEvents): - data_field = "pages" - deleted_events_api_name = "Page" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldPages(MetafieldShopifySubstream): - parent_stream_class: object = Pages - - -class PriceRules(IncrementalShopifyStreamWithDeletedEvents): - data_field = "price_rules" - deleted_events_api_name = "PriceRule" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class DiscountCodes(ShopifySubstream): - parent_stream_class: object = PriceRules - slice_key = "price_rule_id" - data_field = "discount_codes" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - price_rule_id = stream_slice["price_rule_id"] - return f"price_rules/{price_rule_id}/{self.data_field}.json" - - -class Locations(ShopifyStream): - """ - The location API does not support any form of filtering. - https://shopify.dev/api/admin-rest/2021-07/resources/location - - Therefore, only FULL_REFRESH mode is supported. - """ - - data_field = "locations" - - def path(self, **kwargs): - return f"{self.data_field}.json" - - -class MetafieldLocations(MetafieldShopifySubstream): - parent_stream_class: object = Locations - - -class InventoryLevels(ShopifySubstream): - parent_stream_class: object = Locations - slice_key = "location_id" - data_field = "inventory_levels" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - location_id = stream_slice["location_id"] - return f"locations/{location_id}/{self.data_field}.json" - - def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: - records_stream = super().parse_response(response, **kwargs) - - def generate_key(record): - record.update({"id": "|".join((str(record.get("location_id", "")), str(record.get("inventory_item_id", ""))))}) - return record - - # associate the surrogate key - yield from map(generate_key, records_stream) - - -class InventoryItems(ShopifySubstream): - parent_stream_class: object = Products - slice_key = "id" - nested_record = "variants" - nested_record_field_name = "inventory_item_id" - data_field = "inventory_items" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - ids = ",".join(str(x[self.nested_record_field_name]) for x in stream_slice[self.slice_key]) - return f"inventory_items.json?ids={ids}" - - -class FulfillmentOrders(ShopifySubstream): - parent_stream_class: object = Orders - slice_key = "order_id" - data_field = "fulfillment_orders" - cursor_field = "id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - order_id = stream_slice[self.slice_key] - return f"orders/{order_id}/{self.data_field}.json" - - -class Fulfillments(ShopifySubstream): - parent_stream_class: object = Orders - slice_key = "order_id" - data_field = "fulfillments" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - order_id = stream_slice[self.slice_key] - return f"orders/{order_id}/{self.data_field}.json" - - -class Shop(ShopifyStream): - data_field = "shop" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class MetafieldShops(IncrementalShopifyStream): - data_field = "metafields" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class CustomerSavedSearch(IncrementalShopifyStream): - api_version = "2022-01" - cursor_field = "id" - order_field = "id" - data_field = "customer_saved_searches" - filter_field = "since_id" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" - - -class CustomerAddress(ShopifySubstream): - parent_stream_class: object = Customers - slice_key = "id" - data_field = "addresses" - cursor_field = "id" - - def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: - customer_id = stream_slice[self.slice_key] - return f"customers/{customer_id}/{self.data_field}.json" - - -class Countries(ShopifyStream): - data_field = "countries" - - def path(self, **kwargs) -> str: - return f"{self.data_field}.json" +from .scopes import ShopifyScopes +from .streams.streams import ( + AbandonedCheckouts, + Articles, + BalanceTransactions, + Blogs, + Collections, + Collects, + Countries, + CustomCollections, + CustomerAddress, + Customers, + CustomerSavedSearch, + DiscountCodes, + Disputes, + DraftOrders, + FulfillmentOrders, + Fulfillments, + InventoryItems, + InventoryLevels, + Locations, + MetafieldArticles, + MetafieldBlogs, + MetafieldCollections, + MetafieldCustomers, + MetafieldDraftOrders, + MetafieldLocations, + MetafieldOrders, + MetafieldPages, + MetafieldProductImages, + MetafieldProducts, + MetafieldProductVariants, + MetafieldShops, + MetafieldSmartCollections, + OrderRefunds, + OrderRisks, + Orders, + Pages, + PriceRules, + ProductImages, + Products, + ProductsGraphQl, + ProductVariants, + Shop, + SmartCollections, + TenderTransactions, + Transactions, + TransactionsGraphql, +) class ConnectionCheckTest: - def __init__(self, config: Mapping[str, Any]): + def __init__(self, config: Mapping[str, Any]) -> None: self.config = config # use `Shop` as a test stream for connection check self.test_stream = Shop(self.config) @@ -953,7 +89,7 @@ def test_connection(self) -> tuple[bool, str]: return False, "The `Shopify Store` name is missing. Make sure it's entered and valid." try: - response = list(self.test_stream.read_records(sync_mode=None)) + response = list(self.test_stream.read_records(sync_mode=SyncMode.full_refresh)) # check for the shop_id is present in the response shop_id = response[0].get("id") if shop_id is not None: @@ -969,8 +105,38 @@ def test_connection(self) -> tuple[bool, str]: except MissingAccessTokenError: return False, self.describe_error("missing_token_error") + def get_shop_id(self) -> str: + """ + We need to have the `shop_id` value available to have it passed elsewhere and fill-in the missing data. + By the time this method is tiggered, we are sure we've passed the `Connection Checks` and have the `shop_id` value. + """ + response = list(self.test_stream.read_records(sync_mode=SyncMode.full_refresh)) + shop_id = response[0].get("id") + if shop_id: + return shop_id + else: + raise Exception(f"Couldn't get `shop_id`. Actual `response`: {response}.") + class SourceShopify(AbstractSource): + @property + def continue_sync_on_stream_failure(self) -> bool: + return True + + @property + def raise_exception_on_missing_stream(self) -> bool: + return False + + @staticmethod + def get_shop_name(config) -> str: + split_pattern = ".myshopify.com" + shop_name = config.get("shop") + return shop_name.split(split_pattern)[0] if split_pattern in shop_name else shop_name + + @staticmethod + def format_stream_name(name) -> str: + return "".join(x.capitalize() for x in name.split("_")) + def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, any]: """ Testing connection availability for the connector. @@ -979,6 +145,16 @@ def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> config["authenticator"] = ShopifyAuthenticator(config) return ConnectionCheckTest(config).test_connection() + def select_transactions_stream(self, config: Mapping[str, Any]) -> Stream: + """ + Allow the Customer to decide which API type to use when it comes to the `Transactions` stream. + """ + should_fetch_user_id = config.get("fetch_transactions_user_id") + if should_fetch_user_id: + return Transactions(config) + else: + return TransactionsGraphql(config) + def streams(self, config: Mapping[str, Any]) -> List[Stream]: """ Mapping a input config of the user input configuration as defined in the connector spec. @@ -986,16 +162,12 @@ def streams(self, config: Mapping[str, Any]) -> List[Stream]: """ config["shop"] = self.get_shop_name(config) config["authenticator"] = ShopifyAuthenticator(config) - user_scopes = self.get_user_scopes(config) - always_permitted_streams = ["MetafieldShops", "Shop", "Countries"] - permitted_streams = [ - stream - for user_scope in user_scopes - if user_scope["handle"] in SCOPES_MAPPING - for stream in SCOPES_MAPPING.get(user_scope["handle"]) - ] + always_permitted_streams - - # before adding stream to stream_instances list, please add it to SCOPES_MAPPING + # add `shop_id` int value + config["shop_id"] = ConnectionCheckTest(config).get_shop_id() + # define scopes checker + scopes_manager: ShopifyScopes = ShopifyScopes(config) + # get the list of the permitted streams, based on the authenticated user scopes + permitted_streams = scopes_manager.get_permitted_streams() stream_instances = [ AbandonedCheckouts(config), Articles(config), @@ -1038,41 +210,12 @@ def streams(self, config: Mapping[str, Any]) -> List[Stream]: Shop(config), SmartCollections(config), TenderTransactions(config), - Transactions(config), + self.select_transactions_stream(config), CustomerSavedSearch(config), CustomerAddress(config), Countries(config), ] - return [stream_instance for stream_instance in stream_instances if self.format_name(stream_instance.name) in permitted_streams] - - @staticmethod - def get_user_scopes(config): - session = requests.Session() - url = f"https://{config['shop']}.myshopify.com/admin/oauth/access_scopes.json" - headers = config["authenticator"].get_auth_header() - - try: - response = session.get(url, headers=headers).json() - access_scopes = response.get("access_scopes") - except InvalidURL: - raise ShopifyWrongShopNameError(url) - except JSONDecodeError as json_error: - raise ShopifyBadJsonError(json_error) - except (SSLError, ConnectionError) as con_error: - raise ShopifyConnectionError(con_error) - - if access_scopes: - return access_scopes - else: - raise ShopifyAccessScopesError(response) - - @staticmethod - def get_shop_name(config): - split_pattern = ".myshopify.com" - shop_name = config.get("shop") - return shop_name.split(split_pattern)[0] if split_pattern in shop_name else shop_name - - @staticmethod - def format_name(name): - return "".join(x.capitalize() for x in name.split("_")) + return [ + stream_instance for stream_instance in stream_instances if self.format_stream_name(stream_instance.name) in permitted_streams + ] diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/spec.json b/airbyte-integrations/connectors/source-shopify/source_shopify/spec.json index 03629c443fa2..4f965d55addf 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/spec.json +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/spec.json @@ -85,6 +85,18 @@ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", "format": "date", "order": 3 + }, + "bulk_window_in_days": { + "type": "integer", + "title": "GraphQL BULK Date Range in Days", + "description": "Defines what would be a date range per single BULK Job", + "default": 30 + }, + "fetch_transactions_user_id": { + "type": "boolean", + "title": "Add `user_id` to Transactions (slower)", + "description": "Defines which API type (REST/BULK) to use to fetch `Transactions` data. If you are a `Shopify Plus` user, leave the default value to speed up the fetch.", + "default": false } } }, diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/streams/base_streams.py b/airbyte-integrations/connectors/source-shopify/source_shopify/streams/base_streams.py new file mode 100644 index 000000000000..6f423a54ec31 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/streams/base_streams.py @@ -0,0 +1,722 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import logging +from abc import ABC, abstractmethod +from functools import cached_property +from typing import Any, Dict, Iterable, Mapping, MutableMapping, Optional, Union +from urllib.parse import parse_qsl, urlparse + +import pendulum as pdm +import requests +from airbyte_cdk.sources.streams.http import HttpStream +from requests.exceptions import RequestException +from source_shopify.shopify_graphql.bulk.job import ShopifyBulkManager +from source_shopify.shopify_graphql.bulk.query import ShopifyBulkQuery, ShopifyBulkTemplates +from source_shopify.shopify_graphql.bulk.record import ShopifyBulkRecord +from source_shopify.transform import DataTypeEnforcer +from source_shopify.utils import EagerlyCachedStreamState as stream_state_cache +from source_shopify.utils import ShopifyNonRetryableErrors +from source_shopify.utils import ShopifyRateLimiter as limiter + + +class ShopifyStream(HttpStream, ABC): + # define default logger + logger = logging.getLogger("airbyte") + + # Latest Stable Release + api_version = "2023-07" + # Page size + limit = 250 + + primary_key = "id" + order_field = "updated_at" + filter_field = "updated_at_min" + + raise_on_http_errors = True + max_retries = 5 + + def __init__(self, config: Dict) -> None: + super().__init__(authenticator=config["authenticator"]) + self._transformer = DataTypeEnforcer(self.get_json_schema()) + self.config = config + + @property + @abstractmethod + def data_field(self) -> str: + """The name of the field in the response which contains the data""" + + @property + def url_base(self) -> str: + return f"https://{self.config['shop']}.myshopify.com/admin/api/{self.api_version}/" + + @property + def default_filter_field_value(self) -> Union[int, str]: + # certain streams are using `since_id` field as `filter_field`, which requires to use `int` type, + # but many other use `str` values for this, we determine what to use based on `filter_field` value + # by default, we use the user defined `Start Date` as initial value, or 0 for `id`-dependent streams. + return 0 if self.filter_field == "since_id" else (self.config.get("start_date") or "") + + def path(self, **kwargs) -> str: + return f"{self.data_field}.json" + + def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: + next_page = response.links.get("next", None) + if next_page: + return dict(parse_qsl(urlparse(next_page.get("url")).query)) + else: + return None + + def request_params(self, next_page_token: Optional[Mapping[str, Any]] = None, **kwargs) -> MutableMapping[str, Any]: + params = {"limit": self.limit} + if next_page_token: + params.update(**next_page_token) + else: + params["order"] = f"{self.order_field} asc" + params[self.filter_field] = self.default_filter_field_value + return params + + @limiter.balance_rate_limit() + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + if response.status_code is requests.codes.OK: + try: + json_response = response.json() + records = json_response.get(self.data_field, []) if self.data_field is not None else json_response + yield from self.produce_records(records) + except RequestException as e: + self.logger.warning(f"Unexpected error in `parse_ersponse`: {e}, the actual response data: {response.text}") + yield {} + + def produce_records(self, records: Optional[Union[Iterable[Mapping[str, Any]], Mapping[str, Any]]] = None) -> Mapping[str, Any]: + # transform method was implemented according to issue 4841 + # Shopify API returns price fields as a string and it should be converted to number + # this solution designed to convert string into number, but in future can be modified for general purpose + if isinstance(records, dict): + # for cases when we have a single record as dict + # add shop_url to the record to make querying easy + records["shop_url"] = self.config["shop"] + yield self._transformer.transform(records) + else: + # for other cases + for record in records: + # add shop_url to the record to make querying easy + record["shop_url"] = self.config["shop"] + yield self._transformer.transform(record) + + def should_retry(self, response: requests.Response) -> bool: + known_errors = ShopifyNonRetryableErrors(self.name) + status = response.status_code + if status in known_errors.keys(): + setattr(self, "raise_on_http_errors", False) + self.logger.warning(known_errors.get(status)) + return False + else: + return super().should_retry(response) + + +class ShopifyDeletedEventsStream(ShopifyStream): + data_field = "events" + primary_key = "id" + cursor_field = "deleted_at" + + def __init__(self, config: Dict, deleted_events_api_name: str) -> None: + self.deleted_events_api_name = deleted_events_api_name + super().__init__(config) + + @property + def availability_strategy(self) -> None: + """ + No need to apply the `availability strategy` for this service stream. + """ + return None + + def get_json_schema(self) -> None: + """ + No need to apply the `schema` for this service stream. + Return `{}` to satisfy the `self._transformer.transform(record)` logic. + """ + return {} + + def produce_deleted_records_from_events(self, delete_events: Iterable[Mapping[str, Any]] = []) -> Mapping[str, Any]: + for event in delete_events: + yield { + "id": event["subject_id"], + self.cursor_field: event["created_at"], + "updated_at": event["created_at"], + "deleted_message": event["message"], + "deleted_description": event["description"], + "shop_url": event["shop_url"], + } + + def read_records(self, stream_state: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Mapping[str, Any]]: + delete_events = super().read_records(stream_state=stream_state, **kwargs) + yield from self.produce_deleted_records_from_events(delete_events) + + def request_params( + self, + stream_state: Optional[Mapping[str, Any]] = None, + next_page_token: Optional[Mapping[str, Any]] = None, + **kwargs, + ) -> MutableMapping[str, Any]: + params: Mapping[str, Any] = {} + + if next_page_token: + # `filter` and `verb` cannot be passed, when `page_info` is present. + # See https://shopify.dev/api/usage/pagination-rest + params.update(**next_page_token) + else: + params.update(**{"filter": self.deleted_events_api_name, "verb": "destroy"}) + if stream_state: + state = stream_state.get("deleted", {}).get(self.cursor_field) + if state: + params["created_at_min"] = state + return params + + +class IncrementalShopifyStream(ShopifyStream, ABC): + # Setting the check point interval to the limit of the records output + @property + def state_checkpoint_interval(self) -> int: + return super().limit + + # Setting the default cursor field for all streams + cursor_field = "updated_at" + deleted_cursor_field = "deleted_at" + + @property + def default_state_comparison_value(self) -> Union[int, str]: + # certain streams are using `id` field as `cursor_field`, which requires to use `int` type, + # but many other use `str` values for this, we determine what to use based on `cursor_field` value + return 0 if self.cursor_field == "id" else "" + + def get_updated_state( + self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any] + ) -> MutableMapping[str, Any]: + last_record_value = latest_record.get(self.cursor_field) or self.default_state_comparison_value + current_state_value = current_stream_state.get(self.cursor_field) or self.default_state_comparison_value + return {self.cursor_field: max(last_record_value, current_state_value)} + + @stream_state_cache.cache_stream_state + def request_params( + self, stream_state: Optional[Mapping[str, Any]] = None, next_page_token: Optional[Mapping[str, Any]] = None, **kwargs + ) -> MutableMapping[str, Any]: + params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) + # If there is a next page token then we should only send pagination-related parameters. + if not next_page_token: + params["order"] = f"{self.order_field} asc" + if stream_state: + params[self.filter_field] = stream_state.get(self.cursor_field) + return params + + # Parse the `stream_slice` with respect to `stream_state` for `Incremental refresh` + # cases where we slice the stream, the endpoints for those classes don't accept any other filtering, + # but they provide us with the updated_at field in most cases, so we used that as incremental filtering during the order slicing. + def filter_records_newer_than_state( + self, stream_state: Optional[Mapping[str, Any]] = None, records_slice: Optional[Iterable[Mapping]] = None + ) -> Iterable: + # Getting records >= state + if stream_state: + state_value = stream_state.get(self.cursor_field) + for record in records_slice: + if self.cursor_field in record: + record_value = record.get(self.cursor_field, self.default_state_comparison_value) + if record_value: + if record_value >= state_value: + yield record + else: + # old entities could have cursor field in place, but set to null + self.logger.warning( + f"Stream `{self.name}`, Record ID: `{record.get(self.primary_key)}` cursor value is: {record_value}, record is emitted without state comparison" + ) + yield record + else: + # old entities could miss the cursor field + self.logger.warning( + f"Stream `{self.name}`, Record ID: `{record.get(self.primary_key)}` missing cursor field: {self.cursor_field}, record is emitted without state comparison" + ) + yield record + else: + yield from records_slice + + +class IncrementalShopifySubstream(IncrementalShopifyStream): + """ + IncrementalShopifySubstream - provides slicing functionality for streams using parts of data from parent stream. + For example: + - `Refunds Orders` is the entity of `Orders`, + - `OrdersRisks` is the entity of `Orders`, + - `DiscountCodes` is the entity of `PriceRules`, etc. + + :: @ parent_stream - defines the parent stream object to read from + :: @ slice_key - defines the name of the property in stream slices dict. + :: @ nested_record - the name of the field inside of parent stream record. Default is `id`. + :: @ nested_record_field_name - the name of the field inside of nested_record. + :: @ nested_substream - the name of the nested entity inside of parent stream, helps to reduce the number of + API Calls, if present, see `OrderRefunds` stream for more. + """ + + parent_stream_class: Union[ShopifyStream, IncrementalShopifyStream] = None + slice_key: str = None + nested_record: str = "id" + nested_record_field_name: str = None + nested_substream = None + nested_substream_list_field_id = None + + @cached_property + def parent_stream(self) -> Union[ShopifyStream, IncrementalShopifyStream]: + """ + Returns the instance of parent stream, if the substream has a `parent_stream_class` dependency. + """ + return self.parent_stream_class(self.config) if self.parent_stream_class else None + + def get_updated_state( + self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any] + ) -> MutableMapping[str, Any]: + """UPDATING THE STATE OBJECT: + Stream: Transactions + Parent Stream: Orders + Returns: + { + {...}, + "transactions": { + "created_at": "2022-03-03T03:47:45-08:00", + "orders": { + "updated_at": "2022-03-03T03:47:46-08:00" + } + }, + {...}, + } + """ + updated_state = super().get_updated_state(current_stream_state, latest_record) + # add parent_stream_state to `updated_state` + updated_state[self.parent_stream.name] = stream_state_cache.cached_state.get(self.parent_stream.name) + return updated_state + + def request_params(self, next_page_token: Optional[Mapping[str, Any]] = None, **kwargs) -> MutableMapping[str, Any]: + params = {"limit": self.limit} + if next_page_token: + params.update(**next_page_token) + return params + + def stream_slices(self, stream_state: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + """ + Reading the parent stream for slices with structure: + EXAMPLE: for given nested_record as `id` of Orders, + + Outputs: + [ + {slice_key: 123}, + {slice_key: 456}, + {...}, + {slice_key: 999 + ] + """ + sorted_substream_slices = [] + + # reading parent nested stream_state from child stream state + parent_stream_state = stream_state.get(self.parent_stream.name) if stream_state else {} + + # reading the parent stream + for record in self.parent_stream.read_records(stream_state=parent_stream_state, **kwargs): + # updating the `stream_state` with the state of it's parent stream + # to have the child stream sync independently from the parent stream + stream_state_cache.cached_state[self.parent_stream.name] = self.parent_stream.get_updated_state({}, record) + # to limit the number of API Calls and reduce the time of data fetch, + # we can pull the ready data for child_substream, if nested data is present, + # and corresponds to the data of child_substream we need. + if self.nested_substream and self.nested_substream_list_field_id: + if record.get(self.nested_substream): + sorted_substream_slices.extend( + [ + { + self.slice_key: sub_record[self.nested_substream_list_field_id], + self.cursor_field: record[self.nested_substream][0].get( + self.cursor_field, self.default_state_comparison_value + ), + } + for sub_record in record[self.nested_record] + ] + ) + elif self.nested_substream: + if record.get(self.nested_substream): + sorted_substream_slices.append( + { + self.slice_key: record[self.nested_record], + self.cursor_field: record[self.nested_substream][0].get(self.cursor_field, self.default_state_comparison_value), + } + ) + else: + # avoid checking `deleted` records for substreams, a.k.a `Metafields` streams, + # since `deleted` records are not available, thus we avoid HTTP-400 errors. + if self.deleted_cursor_field not in record: + yield {self.slice_key: record[self.nested_record]} + + # output slice from sorted list to avoid filtering older records + if self.nested_substream: + if len(sorted_substream_slices) > 0: + # sort by cursor_field + sorted_substream_slices.sort(key=lambda x: x.get(self.cursor_field)) + for sorted_slice in sorted_substream_slices: + yield {self.slice_key: sorted_slice[self.slice_key]} + + # the stream_state caching is required to avoid the STATE collisions for Substreams + @stream_state_cache.cache_stream_state + def read_records( + self, + stream_state: Optional[Mapping[str, Any]] = None, + stream_slice: Optional[Mapping[str, Any]] = None, + **kwargs, + ) -> Iterable[Mapping[str, Any]]: + """Reading child streams records for each `id`""" + + slice_data = stream_slice.get(self.slice_key) + # sometimes the stream_slice.get(self.slice_key) has the list of records, + # to avoid data exposition inside the logs, we should get the data we need correctly out of stream_slice. + if isinstance(slice_data, list) and self.nested_record_field_name is not None and len(slice_data) > 0: + slice_data = slice_data[0].get(self.nested_record_field_name) + + # reading substream records + self.logger.info(f"Reading {self.name} for {self.slice_key}: {slice_data}") + records = super().read_records(stream_slice=stream_slice, **kwargs) + # get the cached substream state, to avoid state collisions for Incremental Syncs + cached_substream_state = stream_state_cache.cached_state.get(self.name, {}) + # filtering the portion of already emmited substream records using cached state value, + # since the actual `metafields` endpoint doesn't support the server-side filtering using query params + # thus to avoid the duplicates - we filter the records following the cached state, + # which is freezed every time the sync starts using the actual STATE provided, + # while the active STATE is updated during the sync and saved as expected, in the end. + yield from self.filter_records_newer_than_state(stream_state=cached_substream_state, records_slice=records) + + +class MetafieldShopifySubstream(IncrementalShopifySubstream): + slice_key = "id" + data_field = "metafields" + + parent_stream_class: Union[ShopifyStream, IncrementalShopifyStream] = None + + def path(self, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> str: + object_id = stream_slice[self.slice_key] + return f"{self.parent_stream_class.data_field}/{object_id}/{self.data_field}.json" + + +class IncrementalShopifyNestedStream(IncrementalShopifyStream): + """ + IncrementalShopifyNestedStream - provides slicing functionality for streams using parts of data from parent stream. + + For example: + - `refunds` is the entity of `order.refunds`, + - `fulfillments` is the entity of the `order.fulfillments` which is nested sub-entity + + :: @ parent_stream - defines the parent stream object to read from + :: @ mutation_map - defines how the nested record should be populated with additional values, + available from parent record. + Example: + >> mutation_map = {"parent_id": "id"}, + where `parent_id` is the new field that created for each subrecord available. + and `id` is the parent_key named `id`, we take the value from. + + :: @ nested_entity - the name of the nested entity inside of parent stream, helps to reduce the number of + API Calls, if present, see `OrderRefunds` or `Fulfillments` streams for more info. + """ + + data_field = None + parent_stream_class: Union[ShopifyStream, IncrementalShopifyStream] = None + mutation_map: Mapping[str, Any] = None + nested_entity = None + + @cached_property + def parent_stream(self) -> object: + """ + Returns the instance of parent stream, if the substream has a `parent_stream_class` dependency. + """ + return self.parent_stream_class(self.config) if self.parent_stream_class else None + + def path(self, **kwargs) -> str: + """ + NOT USED FOR THIS TYPE OF STREAMS. + """ + return "" + + def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: + """ + NOT USED FOR THIS TYPE OF STREAMS. + """ + return None + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + """ + NOT USED FOR THIS TYPE OF STREAMS. + """ + return {} + + def get_updated_state( + self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any] + ) -> MutableMapping[str, Any]: + """UPDATING THE STATE OBJECT: + Stream: Transactions + Parent Stream: Orders + Returns: + { + {...}, + "transactions": { + "created_at": "2022-03-03T03:47:45-08:00", + "orders": { + "updated_at": "2022-03-03T03:47:46-08:00" + } + }, + {...}, + } + """ + updated_state = super().get_updated_state(current_stream_state, latest_record) + # add parent_stream_state to `updated_state` + updated_state[self.parent_stream.name] = stream_state_cache.cached_state.get(self.parent_stream.name) + return updated_state + + def add_parent_id(self, record: Optional[Mapping[str, Any]] = None) -> Mapping[str, Any]: + """ + Adds new field to the record with name `key` based on the `value` key from record. + """ + if self.mutation_map and record: + for subrecord in record.get(self.nested_entity, []): + for k, v in self.mutation_map.items(): + subrecord[k] = record.get(v) + else: + return record + + # the stream_state caching is required to avoid the STATE collisions for Substreams + @stream_state_cache.cache_stream_state + def stream_slices(self, stream_state: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + parent_stream_state = stream_state.get(self.parent_stream.name) if stream_state else {} + for record in self.parent_stream.read_records(stream_state=parent_stream_state, **kwargs): + # updating the `stream_state` with the state of it's parent stream + # to have the child stream sync independently from the parent stream + stream_state_cache.cached_state[self.parent_stream.name] = self.parent_stream.get_updated_state({}, record) + # to limit the number of API Calls and reduce the time of data fetch, + # we can pull the ready data for child_substream, if nested data is present, + # and corresponds to the data of child_substream we need. + if self.nested_entity in record.keys(): + # add parent_id key, value from mutation_map, if passed. + self.add_parent_id(record) + # yield nested sub-rcords + yield from [{self.nested_entity: sub_record} for sub_record in record.get(self.nested_entity, [])] + + def read_records(self, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Mapping[str, Any]]: + # get the cached substream state, to avoid state collisions for Incremental Syncs + cached_state = stream_state_cache.cached_state.get(self.name, {}) + # emitting nested parent entity + yield from self.filter_records_newer_than_state(cached_state, self.produce_records(stream_slice.get(self.nested_entity, []))) + + +class IncrementalShopifyStreamWithDeletedEvents(IncrementalShopifyStream): + @property + @abstractmethod + def deleted_events_api_name(self) -> str: + """ + The string value of the Shopify Events Object to pull: + + articles -> Article + blogs -> Blog + custom_collections -> Collection + orders -> Order + pages -> Page + price_rules -> PriceRule + products -> Product + + """ + + @property + def deleted_events(self) -> ShopifyDeletedEventsStream: + """ + The Events stream instance to fetch the `destroyed` records for specified `deleted_events_api_name`, like: `Product`. + See more in `ShopifyDeletedEventsStream` class. + """ + return ShopifyDeletedEventsStream(self.config, self.deleted_events_api_name) + + @property + def default_deleted_state_comparison_value(self) -> Union[int, str]: + """ + Set the default STATE comparison value for cases when the deleted record doesn't have it's value. + We expect the `deleted_at` cursor field for destroyed records would be always type of String. + """ + return "" + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + """ + We extend the stream state with `deleted` property to store the `destroyed` records STATE separetely from the Stream State. + """ + state = super().get_updated_state(current_stream_state, latest_record) + # add `deleted` property to each stream supports `deleted events`, + # to provide the `Incremental` sync mode, for the `Incremental Delete` records. + last_deleted_record_value = latest_record.get(self.deleted_cursor_field) or self.default_deleted_state_comparison_value + current_deleted_state_value = current_stream_state.get(self.deleted_cursor_field) or self.default_deleted_state_comparison_value + state["deleted"] = {self.deleted_cursor_field: max(last_deleted_record_value, current_deleted_state_value)} + return state + + def read_records( + self, + stream_state: Optional[Mapping[str, Any]] = None, + stream_slice: Optional[Mapping[str, Any]] = None, + **kwargs, + ) -> Iterable[Mapping[str, Any]]: + """Override to fetch deleted records for supported streams""" + # main records stream + yield from super().read_records(stream_state=stream_state, stream_slice=stream_slice, **kwargs) + # fetch deleted events after the Stream data is pulled + yield from self.deleted_events.read_records(stream_state=stream_state, **kwargs) + + +class IncrementalShopifyGraphQlBulkStream(IncrementalShopifyStream): + filter_field = "updated_at" + cursor_field = "updated_at" + data_field = "graphql" + http_method = "POST" + + parent_stream_class: Optional[Union[ShopifyStream, IncrementalShopifyStream]] = None + + def __init__(self, config: Dict) -> None: + super().__init__(config) + # init BULK Query instance, pass `shop_id` from config + self.query = self.bulk_query(shop_id=config.get("shop_id")) + # define BULK Manager instance + self.job_manager: ShopifyBulkManager = ShopifyBulkManager(self._session, f"{self.url_base}/{self.path()}") + # define Record Producer instance + self.record_producer: ShopifyBulkRecord = ShopifyBulkRecord(self.query) + + @cached_property + def parent_stream(self) -> object: + """ + Returns the instance of parent stream, if the substream has a `parent_stream_class` dependency. + """ + return self.parent_stream_class(self.config) if self.parent_stream_class else None + + @property + def slice_interval_in_days(self) -> int: + """ + Defines date range per single BULK Job. + """ + return self.config.get("bulk_window_in_days", 30) + + @property + @abstractmethod + def bulk_query(self) -> ShopifyBulkQuery: + """ + This method property should be defined in the stream class instance, + and should be instantiated from the `ShopifyBulkQuery` class. + """ + + def add_shop_url_field(self, records: Iterable[MutableMapping[str, Any]] = []) -> Iterable[MutableMapping[str, Any]]: + # ! Mandatory, add shop_url to the record to make querying easy + # more info: https://github.com/airbytehq/airbyte/issues/25110 + for record in records: + if record: + record["shop_url"] = self.config["shop"] + yield record + + @property + def default_state_comparison_value(self) -> Union[int, str]: + # certain streams are using `id` field as `cursor_field`, which requires to use `int` type, + # but many other use `str` values for this, we determine what to use based on `cursor_field` value + return 0 if self.cursor_field == "id" else self.config.get("start_date") + + # CDK OVERIDES + @property + def availability_strategy(self) -> None: + """NOT USED FOR BULK OPERATIONS TO SAVE THE RATE LIMITS AND TIME FOR THE SYNC.""" + return None + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + """ + NOT USED FOR SHOPIFY BULK OPERARTIONS. + https://shopify.dev/docs/api/usage/bulk-operations/queries#write-a-bulk-operation + """ + return {} + + def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: + """ + NOT USED FOR SHOPIFY BULK OPERATIONS. + https://shopify.dev/docs/api/usage/bulk-operations/queries#write-a-bulk-operation + """ + return None + + def request_body_json(self, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> Mapping[str, Any]: + """ + Override for _send_request CDK method to send HTTP request to Shopify BULK Operatoions. + https://shopify.dev/docs/api/usage/bulk-operations/queries#bulk-query-overview + """ + return {"query": ShopifyBulkTemplates.prepare(stream_slice.get("query"))} + + def get_updated_state( + self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any] + ) -> MutableMapping[str, Any]: + """UPDATING THE STATE OBJECT: + Stream: CustomerAddress + Parent Stream: Customers + Returns: + { + "customer_address": { + "id": 12345, + "customers": { + "updated_at": "2022-03-03T03:47:46-08:00" + } + } + } + """ + updated_state = super().get_updated_state(current_stream_state, latest_record) + if self.parent_stream_class: + # add parent_stream_state to `updated_state` + updated_state[self.parent_stream.name] = {self.parent_stream.cursor_field: latest_record.get(self.parent_stream.cursor_field)} + return updated_state + + def get_state_value(self, stream_state: Mapping[str, Any] = None) -> Optional[Union[str, int]]: + if stream_state: + if self.parent_stream_class: + # get parent stream state from the stream_state object. + parent_state = stream_state.get(self.parent_stream.name, {}) + if parent_state: + return parent_state.get(self.parent_stream.cursor_field, self.default_state_comparison_value) + else: + # get the stream state, if no `parent_stream_class` was assigned. + return stream_state.get(self.cursor_field, self.default_state_comparison_value) + else: + # for majority of cases we fallback to start_date, otherwise. + return self.config.get("start_date") + + @stream_state_cache.cache_stream_state + def stream_slices(self, stream_state: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + if self.filter_field: + state = self.get_state_value(stream_state) + start = pdm.parse(state) + end = pdm.now() + while start < end: + slice_end = start.add(days=self.slice_interval_in_days) + # check end period is less than now() or now() is applied otherwise. + slice_end = slice_end if slice_end < end else end + # making pre-defined sliced query to pass it directly + prepared_query = self.query.get(self.filter_field, start.to_rfc3339_string(), slice_end.to_rfc3339_string()) + self.logger.info(f"Stream: `{self.name}` requesting BULK Job for period: {start} -- {slice_end}.") + yield {"query": prepared_query} + start = slice_end + else: + # for the streams that don't support filtering + yield {"query": self.query.get()} + + def process_bulk_results( + self, response: requests.Response, stream_state: Optional[Mapping[str, Any]] = None + ) -> Iterable[Mapping[str, Any]]: + # get results fetched from COMPLETED BULK Job or `None` + filename = self.job_manager.job_check(response) + # the `filename` could be `None`, meaning there are no data available for the slice period. + if filename: + # add `shop_url` field to each record produced + records = self.add_shop_url_field( + # produce records from saved bulk job result + self.record_producer.read_file(filename) + ) + yield from self.filter_records_newer_than_state(stream_state, records) + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + # get the cached substream state, to avoid state collisions for Incremental Syncs + stream_state = stream_state_cache.cached_state.get(self.name, {self.cursor_field: self.default_state_comparison_value}) + yield from self.process_bulk_results(response, stream_state) diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/streams/streams.py b/airbyte-integrations/connectors/source-shopify/source_shopify/streams/streams.py new file mode 100644 index 000000000000..d528ed0105b2 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/streams/streams.py @@ -0,0 +1,388 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +from typing import Any, Iterable, Mapping, MutableMapping, Optional + +import requests +from airbyte_cdk.sources.streams.core import package_name_from_class +from airbyte_cdk.sources.utils.schema_helpers import ResourceSchemaLoader +from requests.exceptions import RequestException +from source_shopify.shopify_graphql.bulk.query import ( + Collection, + CustomerAddresses, + DiscountCode, + FulfillmentOrder, + InventoryItem, + InventoryLevel, + MetafieldCollection, + MetafieldCustomer, + MetafieldDraftOrder, + MetafieldLocation, + MetafieldOrder, + MetafieldProduct, + MetafieldProductImage, + MetafieldProductVariant, + Transaction, +) +from source_shopify.shopify_graphql.graphql import get_query_products +from source_shopify.utils import ApiTypeEnum +from source_shopify.utils import ShopifyRateLimiter as limiter + +from .base_streams import ( + IncrementalShopifyGraphQlBulkStream, + IncrementalShopifyNestedStream, + IncrementalShopifyStream, + IncrementalShopifyStreamWithDeletedEvents, + IncrementalShopifySubstream, + MetafieldShopifySubstream, + ShopifyStream, +) + + +class Articles(IncrementalShopifyStreamWithDeletedEvents): + data_field = "articles" + cursor_field = "id" + order_field = "id" + filter_field = "since_id" + deleted_events_api_name = "Article" + + +class MetafieldArticles(MetafieldShopifySubstream): + parent_stream_class = Articles + + +class Blogs(IncrementalShopifyStreamWithDeletedEvents): + cursor_field = "id" + order_field = "id" + data_field = "blogs" + filter_field = "since_id" + deleted_events_api_name = "Blog" + + +class MetafieldBlogs(MetafieldShopifySubstream): + parent_stream_class = Blogs + + +class Customers(IncrementalShopifyStream): + data_field = "customers" + + +class MetafieldCustomers(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldCustomer = MetafieldCustomer + + +class Orders(IncrementalShopifyStreamWithDeletedEvents): + data_field = "orders" + deleted_events_api_name = "Order" + + def request_params( + self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs + ) -> MutableMapping[str, Any]: + params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) + if not next_page_token: + params["status"] = "any" + return params + + +class Disputes(IncrementalShopifyStream): + data_field = "disputes" + filter_field = "since_id" + cursor_field = "id" + order_field = "id" + + def path(self, **kwargs) -> str: + return f"shopify_payments/{self.data_field}.json" + + +class MetafieldOrders(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldOrder = MetafieldOrder + + +class DraftOrders(IncrementalShopifyStream): + data_field = "draft_orders" + + +class MetafieldDraftOrders(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldDraftOrder = MetafieldDraftOrder + + +class Products(IncrementalShopifyStreamWithDeletedEvents): + use_cache = True + data_field = "products" + deleted_events_api_name = "Product" + + +class ProductsGraphQl(IncrementalShopifyStream): + filter_field = "updatedAt" + cursor_field = "updatedAt" + data_field = "graphql" + http_method = "POST" + + def request_params( + self, + stream_state: Optional[Mapping[str, Any]] = None, + next_page_token: Optional[Mapping[str, Any]] = None, + **kwargs, + ) -> MutableMapping[str, Any]: + return {} + + def request_body_json( + self, + stream_state: Mapping[str, Any], + stream_slice: Optional[Mapping[str, Any]] = None, + next_page_token: Optional[Mapping[str, Any]] = None, + ) -> Optional[Mapping]: + state_value = stream_state.get(self.filter_field) + if state_value: + filter_value = state_value + else: + filter_value = self.default_filter_field_value + query = get_query_products( + first=self.limit, filter_field=self.filter_field, filter_value=filter_value, next_page_token=next_page_token + ) + return {"query": query} + + @staticmethod + def next_page_token(response: requests.Response) -> Optional[Mapping[str, Any]]: + page_info = response.json()["data"]["products"]["pageInfo"] + has_next_page = page_info["hasNextPage"] + if has_next_page: + return page_info["endCursor"] + else: + return None + + @limiter.balance_rate_limit(api_type=ApiTypeEnum.graphql.value) + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + if response.status_code is requests.codes.OK: + try: + json_response = response.json()["data"]["products"]["nodes"] + yield from self.produce_records(json_response) + except RequestException as e: + self.logger.warning(f"Unexpected error in `parse_ersponse`: {e}, the actual response data: {response.text}") + + +class MetafieldProducts(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldProduct = MetafieldProduct + + +class ProductImages(IncrementalShopifyNestedStream): + parent_stream_class = Products + nested_entity = "images" + # add `product_id` to each nested subrecord + mutation_map = {"product_id": "id"} + + +class MetafieldProductImages(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldProductImage = MetafieldProductImage + + +class ProductVariants(IncrementalShopifyNestedStream): + parent_stream_class = Products + nested_entity = "variants" + # add `product_id` to each nested subrecord + mutation_map = {"product_id": "id"} + + +class MetafieldProductVariants(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldProductVariant = MetafieldProductVariant + + +class AbandonedCheckouts(IncrementalShopifyStream): + data_field = "checkouts" + + def request_params( + self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs + ) -> MutableMapping[str, Any]: + params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs) + # If there is a next page token then we should only send pagination-related parameters. + if not next_page_token: + params["status"] = "any" + return params + + +class CustomCollections(IncrementalShopifyStreamWithDeletedEvents): + data_field = "custom_collections" + deleted_events_api_name = "Collection" + + +class SmartCollections(IncrementalShopifyStream): + data_field = "smart_collections" + + +class MetafieldSmartCollections(MetafieldShopifySubstream): + parent_stream_class = SmartCollections + + +class Collects(IncrementalShopifyStream): + """ + Collects stream does not support Incremental Refresh based on datetime fields, only `since_id` is supported: + https://shopify.dev/docs/admin-api/rest/reference/products/collect + + The Collect stream is the link between Products and Collections, if the Collection is created for Products, + the `collect` record is created, it's reasonable to Full Refresh all collects. As for Incremental refresh - + we would use the since_id specificaly for this stream. + """ + + data_field = "collects" + cursor_field = "id" + order_field = "id" + filter_field = "since_id" + + +class Collections(IncrementalShopifyGraphQlBulkStream): + bulk_query: Collection = Collection + + +class MetafieldCollections(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldCollection = MetafieldCollection + + +class BalanceTransactions(IncrementalShopifyStream): + + """ + PaymentsTransactions stream does not support Incremental Refresh based on datetime fields, only `since_id` is supported: + https://shopify.dev/api/admin-rest/2021-07/resources/transactions + """ + + data_field = "transactions" + cursor_field = "id" + order_field = "id" + filter_field = "since_id" + + def path(self, **kwargs) -> str: + return f"shopify_payments/balance/{self.data_field}.json" + + +class OrderRefunds(IncrementalShopifyNestedStream): + parent_stream_class = Orders + # override default cursor field + cursor_field = "created_at" + nested_entity = "refunds" + + +class OrderRisks(IncrementalShopifySubstream): + parent_stream_class = Orders + slice_key = "order_id" + data_field = "risks" + cursor_field = "id" + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + order_id = stream_slice["order_id"] + return f"orders/{order_id}/{self.data_field}.json" + + +class Transactions(IncrementalShopifySubstream): + parent_stream_class = Orders + slice_key = "order_id" + data_field = "transactions" + cursor_field = "created_at" + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + order_id = stream_slice["order_id"] + return f"orders/{order_id}/{self.data_field}.json" + + +class TransactionsGraphql(IncrementalShopifyGraphQlBulkStream): + bulk_query: Transaction = Transaction + cursor_field = "created_at" + + @property + def name(self) -> str: + # override default name. This stream is essentially the same as `Transactions` stream, but it's using GraphQL API, which does not include the user_id field + return "transactions" + + def get_json_schema(self) -> Mapping[str, Any]: + """ + This stream has the same schema as `Transactions` stream, except of: + - fields: [ `device_id, source_name, user_id, location_id` ] + + Specifically: + - `user_id` field requires `Shopify Plus` / be authorised via `Financialy Embedded App`. + - additional `read_users` scope is required https://shopify.dev/docs/api/usage/access-scopes#authenticated-access-scopes + """ + return ResourceSchemaLoader(package_name_from_class(Transactions)).get_schema("transactions") + + +class TenderTransactions(IncrementalShopifyStream): + data_field = "tender_transactions" + cursor_field = "processed_at" + filter_field = "processed_at_min" + + +class Pages(IncrementalShopifyStreamWithDeletedEvents): + data_field = "pages" + deleted_events_api_name = "Page" + + +class MetafieldPages(MetafieldShopifySubstream): + parent_stream_class = Pages + + +class PriceRules(IncrementalShopifyStreamWithDeletedEvents): + data_field = "price_rules" + deleted_events_api_name = "PriceRule" + + +class DiscountCodes(IncrementalShopifyGraphQlBulkStream): + bulk_query: DiscountCode = DiscountCode + + +class Locations(ShopifyStream): + """ + The location API does not support any form of filtering. + https://shopify.dev/api/admin-rest/2021-07/resources/location + + Therefore, only FULL_REFRESH mode is supported. + """ + + data_field = "locations" + + +class MetafieldLocations(IncrementalShopifyGraphQlBulkStream): + bulk_query: MetafieldLocation = MetafieldLocation + filter_field = None + + +class InventoryLevels(IncrementalShopifyGraphQlBulkStream): + bulk_query: InventoryLevel = InventoryLevel + + +class InventoryItems(IncrementalShopifyGraphQlBulkStream): + bulk_query: InventoryItem = InventoryItem + + +class FulfillmentOrders(IncrementalShopifyGraphQlBulkStream): + bulk_query: FulfillmentOrder = FulfillmentOrder + + +class Fulfillments(IncrementalShopifyNestedStream): + parent_stream_class = Orders + nested_entity = "fulfillments" + + +class Shop(ShopifyStream): + data_field = "shop" + + +class MetafieldShops(IncrementalShopifyStream): + data_field = "metafields" + + +class CustomerSavedSearch(IncrementalShopifyStream): + api_version = "2022-01" + cursor_field = "id" + order_field = "id" + data_field = "customer_saved_searches" + filter_field = "since_id" + + +class CustomerAddress(IncrementalShopifyGraphQlBulkStream): + parent_stream_class = Customers + bulk_query: CustomerAddresses = CustomerAddresses + cursor_field = "id" + + +class Countries(ShopifyStream): + data_field = "countries" diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/transform.py b/airbyte-integrations/connectors/source-shopify/source_shopify/transform.py index 87b1e82b3107..496e527b09e4 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/transform.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/transform.py @@ -41,6 +41,9 @@ def _get_json_types(value_type: Any) -> List[str]: type(None): [ "null", ], + # overflow, when we need to read nested entity from the parent record, + # that has been already transformed. + Decimal: ["number"], } return json_types.get(value_type) diff --git a/airbyte-integrations/connectors/source-shopify/source_shopify/utils.py b/airbyte-integrations/connectors/source-shopify/source_shopify/utils.py index 4eab2e65cd2f..46cb2c18b5f6 100644 --- a/airbyte-integrations/connectors/source-shopify/source_shopify/utils.py +++ b/airbyte-integrations/connectors/source-shopify/source_shopify/utils.py @@ -6,72 +6,11 @@ import enum from functools import wraps from time import sleep -from typing import Any, Dict, List, Mapping, Optional +from typing import Any, Callable, Dict, List, Mapping, Optional import requests - -SCOPES_MAPPING = { - "read_customers": [ - "Customers", - "MetafieldCustomers", - "CustomerSavedSearch", - "CustomerAddress", - ], - "read_orders": [ - "Orders", - "AbandonedCheckouts", - "TenderTransactions", - "Transactions", - "Fulfillments", - "OrderRefunds", - "OrderRisks", - "MetafieldOrders", - ], - "read_draft_orders": [ - "DraftOrders", - "MetafieldDraftOrders", - ], - "read_products": [ - "Products", - "ProductsGraphQl", - "MetafieldProducts", - "ProductImages", - "MetafieldProductImages", - "MetafieldProductVariants", - "CustomCollections", - "Collects", - "Collections", - "ProductVariants", - "MetafieldCollections", - "SmartCollections", - "MetafieldSmartCollections", - ], - "read_content": [ - "Pages", - "MetafieldPages", - ], - "read_price_rules": ["PriceRules"], - "read_discounts": ["DiscountCodes"], - "read_locations": [ - "Locations", - "MetafieldLocations", - ], - "read_inventory": [ - "InventoryItems", - "InventoryLevels", - ], - "read_merchant_managed_fulfillment_orders": ["FulfillmentOrders"], - "read_shopify_payments_payouts": [ - "BalanceTransactions", - "Disputes", - ], - "read_online_store_pages": [ - "Articles", - "MetafieldArticles", - "Blogs", - "MetafieldBlogs", - ], -} +from airbyte_cdk.utils import AirbyteTracedException +from airbyte_protocol.models import FailureType class ShopifyNonRetryableErrors: @@ -88,38 +27,38 @@ def __new__(self, stream: str) -> Mapping[str, Any]: } -class ShopifyAccessScopesError(Exception): +class ShopifyAccessScopesError(AirbyteTracedException): """Raises the error if authenticated user doesn't have access to verify the grantted scopes.""" help_url = "https://shopify.dev/docs/api/usage/access-scopes#authenticated-access-scopes" - def __init__(self, response): - super().__init__( - f"Reason: Scopes are not available, make sure you're using the correct `Shopify Store` name. Actual response: {response}. More info about: {self.help_url}" - ) + def __init__(self, response, **kwargs) -> None: + self.message = f"Reason: Scopes are not available, make sure you're using the correct `Shopify Store` name. Actual response: {response}. More info about: {self.help_url}" + super().__init__(internal_message=self.message, failure_type=FailureType.config_error, **kwargs) -class ShopifyBadJsonError(ShopifyAccessScopesError): +class ShopifyBadJsonError(AirbyteTracedException): """Raises the error when Shopify replies with broken json for `access_scopes` request""" - def __init__(self, message): - super().__init__(f"Reason: Bad JSON Response from the Shopify server. Details: {message}.") + def __init__(self, message, **kwargs) -> None: + self.message = f"Reason: Bad JSON Response from the Shopify server. Details: {message}." + super().__init__(internal_message=self.message, failure_type=FailureType.config_error, **kwargs) -class ShopifyConnectionError(ShopifyAccessScopesError): - """Raises the error when Shopify replies with broken connection error for `access_scopes` request""" +class ShopifyConnectionError(AirbyteTracedException): + """Raises the error when Shopify resources couldn't be accessed because of the ConnectionError occured (100-x)""" - def __init__(self, details): - super().__init__(f"Invalid `Shopify Store` name used or `host` couldn't be verified by Shopify. Details: {details}") + def __init__(self, details, **kwargs) -> None: + self.message = f"Invalid `Shopify Store` name used or `host` couldn't be verified by Shopify. Details: {details}" + super().__init__(internal_message=self.message, failure_type=FailureType.config_error, **kwargs) -class ShopifyWrongShopNameError(Exception): +class ShopifyWrongShopNameError(AirbyteTracedException): """Raises the error when `Shopify Store` name is incorrect or couldn't be verified by the Shopify""" - def __init__(self, url): - super().__init__( - f"Reason: The `Shopify Store` name is invalid or missing for `input configuration`, make sure it's valid. Details: {url}" - ) + def __init__(self, url, **kwargs) -> None: + self.message = f"The `Shopify Store` name is invalid or missing for `input configuration`, make sure it's valid. Details: {url}" + super().__init__(internal_message=self.message, failure_type=FailureType.config_error, **kwargs) class UnrecognisedApiType(Exception): @@ -175,7 +114,7 @@ def _convert_load_to_time(load: Optional[float], threshold: float) -> float: return wait_time @staticmethod - def get_rest_api_wait_time(*args, threshold: float = 0.9, rate_limit_header: str = "X-Shopify-Shop-Api-Call-Limit"): + def get_rest_api_wait_time(*args, threshold: float = 0.9, rate_limit_header: str = "X-Shopify-Shop-Api-Call-Limit") -> float: """ To avoid reaching Shopify REST API Rate Limits, use the "X-Shopify-Shop-Api-Call-Limit" header value, to determine the current rate limits and load and handle wait_time based on load %. @@ -206,7 +145,7 @@ def get_rest_api_wait_time(*args, threshold: float = 0.9, rate_limit_header: str return wait_time @staticmethod - def get_graphql_api_wait_time(*args, threshold: float = 0.9): + def get_graphql_api_wait_time(*args, threshold: float = 0.9) -> float: """ To avoid reaching Shopify Graphql API Rate Limits, use the extensions dict in the response. @@ -254,7 +193,7 @@ def get_graphql_api_wait_time(*args, threshold: float = 0.9): return wait_time @staticmethod - def wait_time(wait_time: float): + def wait_time(wait_time: float) -> None: return sleep(wait_time) @staticmethod @@ -262,15 +201,15 @@ def balance_rate_limit( threshold: float = 0.9, rate_limit_header: str = "X-Shopify-Shop-Api-Call-Limit", api_type: ApiTypeEnum = ApiTypeEnum.rest.value, - ): + ) -> Callable[..., Any]: """ The decorator function. Adjust `threshold`, `rate_limit_header` and `api_type` if needed. """ - def decorator(func): + def decorator(func) -> Callable[..., Any]: @wraps(func) - def wrapper_balance_rate_limit(*args, **kwargs): + def wrapper_balance_rate_limit(*args, **kwargs) -> Any: if api_type == ApiTypeEnum.rest.value: ShopifyRateLimiter.wait_time( ShopifyRateLimiter.get_rest_api_wait_time(*args, threshold=threshold, rate_limit_header=rate_limit_header) @@ -310,7 +249,7 @@ def stream_state_to_tmp(*args, state_object: Dict = cached_state, **kwargs) -> D # Map the input *args, the sequece should be always keeped up to the input function # change the mapping if needed stream: object = args[0] # the self instance of the stream - current_stream_state: Dict = kwargs["stream_state"] or {} + current_stream_state: Dict = kwargs.get("stream_state") or {} # get the current tmp_state_value tmp_stream_state_value = state_object.get(stream.name, {}).get(stream.cursor_field, "") # Save the curent stream value for current sync, if present. @@ -324,9 +263,9 @@ def stream_state_to_tmp(*args, state_object: Dict = cached_state, **kwargs) -> D return state_object - def cache_stream_state(func): + def cache_stream_state(func) -> Callable[..., Any]: @wraps(func) - def decorator(*args, **kwargs): + def decorator(*args, **kwargs) -> Any: EagerlyCachedStreamState.stream_state_to_tmp(*args, **kwargs) return func(*args, **kwargs) diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/conftest.py b/airbyte-integrations/connectors/source-shopify/unit_tests/conftest.py index e8e250524894..6b7d9e7cb0e4 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/conftest.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/conftest.py @@ -3,6 +3,8 @@ # import os +from json import dumps +from typing import Any import pytest import requests @@ -26,6 +28,7 @@ def basic_config(): def auth_config(): return { "shop": "test_shop", + "start_date": "2023-01-01", "credentials": {"auth_method": "api_password", "api_password": "api_password"}, "authenticator": None, } @@ -55,3 +58,800 @@ def response_with_bad_json(): response.status_code = 200 response._content = bad_json_str.encode("utf-8") return response + + +@pytest.fixture +def bulk_error() -> dict[str, Any]: + return { + "data": { + "bulkOperationRunQuery": { + "bulkOperation": None, + "userErrors": [ + { + "field": "some_field", + "message": "something wrong with the requested field.", + }, + ], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_unknown_error() -> dict[str, Any]: + return { + "errors": [ + { + "message": "something wrong with the job", + }, + ], + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_no_errors() -> dict[str, Any]: + return {} + + +@pytest.fixture +def bulk_error_with_concurrent_job(): + return { + "data": { + "bulkOperationRunQuery": { + "bulkOperation": None, + "userErrors": [ + { + "field": None, + "message": "", + }, + { + "field": None, + "message": "A bulk query operation for this app and shop is already in progress: gid://shopify/BulkOperation/4046676525245.", + }, + ], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_successful_response(): + return { + "data": { + "bulkOperationRunQuery": { + "bulkOperation": { + "id": "gid://shopify/BulkOperation/4046733967549", + "status": "CREATED", + }, + "userErrors": [], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_successful_response_with_errors(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4046733967549", + "status": "RUNNING", + }, + "bulkOperationRunQuery": { + "userErrors": [ + { + "message": "something wrong with the job", + }, + ], + }, + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_successful_response_with_no_id(): + return { + "data": { + "bulkOperationRunQuery": { + "bulkOperation": { + "status": "RUNNING", + }, + "userErrors": [], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_successful_completed_response(): + return { + "data": { + "bulkOperationRunQuery": { + "bulkOperation": { + "id": "gid://shopify/BulkOperation/4046733967549", + "status": "CREATED", + "url": '"https://some_url/response-content-disposition=attachment;+filename="bulk-123456789.jsonl";+filename*=UTF-8' + 'bulk-4047416819901.jsonl&response-content-type=application/jsonl"', + }, + "userErrors": [], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_created_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4046733967549", + "status": "CREATED", + "userErrors": [], + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 10, + "actualQueryCost": 10, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 990, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_completed_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": "COMPLETED", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": 'https://some_url?response-content-disposition=attachment;+filename="bulk-123456789.jsonl";+filename*=UTF-8' + "bulk-123456789.jsonl&response-content-type=application/jsonl", + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_failed_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": "FAILED", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_timeout_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": "TIMEOUT", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_running_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": "RUNNING", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_running_response_without_id(): + return { + "data": { + "node": { + # "id": "gid://shopify/BulkOperation/4047052112061", + "status": "RUNNING", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_access_denied_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": "ACCESS_DENIED", + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def bulk_job_unknown_status_response(): + return { + "data": { + "node": { + "id": "gid://shopify/BulkOperation/4047052112061", + "status": None, + "errorCode": None, + "objectCount": "0", + "fileSize": None, + "url": None, + "partialDataUrl": None, + } + }, + "extensions": { + "cost": { + "requestedQueryCost": 1, + "actualQueryCost": 1, + "throttleStatus": { + "maximumAvailable": 1000.0, + "currentlyAvailable": 999, + "restoreRate": 50.0, + }, + } + }, + } + + +@pytest.fixture +def metafield_jsonl_content_example(): + return ( + dumps( + { + "__typename": "Metafield", + "id": "gid://shopify/Metafield/123", + "__parentId": "gid://shopify/Order/1234567", + "createdAt": "2023-01-01T01:01:01Z", + "updatedAt": "2023-01-01T01:01:01Z", + } + ) + + "\n" + ) + + +@pytest.fixture +def filfillment_order_jsonl_content_example(): + return """{"__typename":"Order","id":"gid:\/\/shopify\/Order\/1"} +{"__typename":"FulfillmentOrder","id":"gid:\/\/shopify\/FulfillmentOrder\/2","assignedLocation":{"address1":"Test","address2":null,"city":"Test","countryCode":"Test","name":"Test","phone":"","province":null,"zip":"00000","location":{"locationId":"gid:\/\/shopify\/Location\/123"}},"destination":{"id":"gid:\/\/shopify\/Destination\/777"},"deliveryMethod":{"id":"gid:\/\/shopify\/DeliveryMethod\/123","methodType":"SHIPPING","minDeliveryDateTime":"2023-04-13T12:00:00Z","maxDeliveryDateTime":"2023-04-13T12:00:00Z"},"fulfillAt":"2023-04-13T12:00:00Z","fulfillBy":null,"internationalDuties":null,"fulfillmentHolds":[{}],"createdAt":"2023-04-13T12:09:45Z","updatedAt":"2023-04-13T12:09:46Z","requestStatus":"UNSUBMITTED","status":"CLOSED","supportedActions":[{}],"__parentId":"gid:\/\/shopify\/Order\/1"} +{"__typename":"FulfillmentOrderLineItem","id":"gid:\/\/shopify\/FulfillmentOrderLineItem\/3","inventoryItemId":"gid:\/\/shopify\/InventoryItem\/33","lineItem":{"lineItemId":"gid:\/\/shopify\/LineItem\/31","fulfillableQuantity":0,"quantity":1,"variant":{"variantId":"gid:\/\/shopify\/ProductVariant\/333"}},"__parentId":"gid:\/\/shopify\/FulfillmentOrder\/2"} +{"__typename":"FulfillmentOrderMerchantRequest","id":"gid:\/\/shopify\/FulfillmentOrderMerchantRequest\/333","message":null,"kind":"FULFILLMENT_REQUEST","requestOptions":{"notify_customer":true},"__parentId":"gid:\/\/shopify\/FulfillmentOrder\/2"}\n""" + + +@pytest.fixture +def inventory_items_jsonl_content_example(): + return """{"__typename":"InventoryItem","id":"gid:\/\/shopify\/InventoryItem\/44871665713341","unitCost":null,"countryCodeOfOrigin":null,"harmonizedSystemCode":null,"provinceCodeOfOrigin":null,"updatedAt":"2023-04-14T10:29:27Z","createdAt":"2023-04-14T10:29:27Z","sku":"","tracked":true,"requiresShipping":false} +{"__typename":"InventoryItem","id":"gid:\/\/shopify\/InventoryItem\/45419395743933","unitCost":{"cost":"29.0"},"countryCodeOfOrigin":"UA","harmonizedSystemCode":"330510","provinceCodeOfOrigin":null,"updatedAt":"2023-12-11T10:37:41Z","createdAt":"2023-12-11T10:37:41Z","sku":"123","tracked":true,"requiresShipping":true}\n""" + + +@pytest.fixture +def customer_address_jsonl_content_example(): + return """{"__typename":"Customer","id":"gid:\/\/shopify\/Customer\/123","defaultAddress":{"id":"gid:\/\/shopify\/MailingAddress\/123?model_name=CustomerAddress"},"addresses":[{"address1":"My Best Accent","address2":"","city":"Fair Lawn","country":"United States","countryCode":"US","company":"Test Company","firstName":"New Test","id":"gid:\/\/shopify\/MailingAddress\/123?model_name=CustomerAddress","lastName":"Customer","name":"New Test Customer","phone":"","province":"New Jersey","provinceCode":"NJ","zip":"07410"}],"updatedAt":"2023-04-24T13:53:48Z"} +{"__typename":"Customer","id":"gid:\/\/shopify\/Customer\/456","defaultAddress":{"id":"gid:\/\/shopify\/MailingAddress\/456?model_name=CustomerAddress"},"addresses":[{"address1":null,"address2":null,"city":null,"country":null,"countryCode":null,"company":null,"firstName":"MArcos","id":"gid:\/\/shopify\/MailingAddress\/456?model_name=CustomerAddress","lastName":"Millnitz","name":"MArcos Millnitz","phone":null,"province":null,"provinceCode":null,"zip":null}],"updatedAt":"2023-07-11T20:07:45Z"}\n""" + + +@pytest.fixture +def inventory_levels_jsonl_content_example(): + return """{"__typename":"Location","id":"gid:\/\/shopify\/Location\/63590301885"} +{"__typename":"InventoryLevel","id":"gid:\/\/shopify\/InventoryLevel\/97912455357?inventory_item_id=42185200631997","available":15,"item":{"inventory_item_id":"gid:\/\/shopify\/InventoryItem\/42185200631997"},"updatedAt":"2023-04-13T12:00:55Z","__parentId":"gid:\/\/shopify\/Location\/63590301885"} +{"__typename":"InventoryLevel","id":"gid:\/\/shopify\/InventoryLevel\/97912455357?inventory_item_id=42185218719933","available":8,"item":{"inventory_item_id":"gid:\/\/shopify\/InventoryItem\/42185218719933"},"updatedAt":"2023-04-13T12:09:45Z","__parentId":"gid:\/\/shopify\/Location\/63590301885"}\n""" + + +@pytest.fixture +def discount_codes_jsonl_content_example(): + return """{"__typename":"DiscountCodeNode","id":"gid:\/\/shopify\/DiscountCodeNode\/945205379261","codeDiscount":{"updatedAt":"2023-12-07T11:40:44Z","createdAt":"2021-07-08T12:40:37Z","summary":"Free shipping on all products • Minimum purchase of $1.00 • For all countries","discountType":"SHIPPING"}} +{"__typename":"DiscountRedeemCode","usageCount":0,"code":"TEST","id":"gid:\/\/shopify\/DiscountRedeemCode\/11545139282109","__parentId":"gid:\/\/shopify\/DiscountCodeNode\/945205379261"} +{"__typename":"DiscountRedeemCode","usageCount":0,"code":"TEST2","id":"gid:\/\/shopify\/DiscountRedeemCode\/13175793582269","__parentId":"gid:\/\/shopify\/DiscountCodeNode\/945205379261"}\n""" + + +@pytest.fixture +def collections_jsonl_content_example(): + return """{"__typename":"Collection","id":"gid:\/\/shopify\/Collection\/270889287869","handle":"frontpage","title":"Home page","updatedAt":"2023-09-05T14:06:59Z","bodyHtml":"updated_mon_24.04.2023","sortOrder":"BEST_SELLING","templateSuffix":"","productsCount":1} +{"__typename":"CollectionPublication","publishedAt":"2021-06-23T01:00:25Z","__parentId":"gid:\/\/shopify\/Collection\/270889287869"} +{"__typename":"CollectionPublication","publishedAt":"2021-08-18T09:39:34Z","__parentId":"gid:\/\/shopify\/Collection\/270889287869"} +{"__typename":"CollectionPublication","publishedAt":"2023-04-20T11:12:24Z","__parentId":"gid:\/\/shopify\/Collection\/270889287869"} +{"__typename":"Collection","id":"gid:\/\/shopify\/Collection\/273278566589","handle":"test-collection","title":"Test Collection","updatedAt":"2023-09-05T14:12:04Z","bodyHtml":"updated_mon_24.04.2023","sortOrder":"BEST_SELLING","templateSuffix":"","productsCount":26} +{"__typename":"CollectionPublication","publishedAt":"2021-07-19T14:02:54Z","__parentId":"gid:\/\/shopify\/Collection\/273278566589"} +{"__typename":"CollectionPublication","publishedAt":"2021-08-18T09:39:34Z","__parentId":"gid:\/\/shopify\/Collection\/273278566589"} +{"__typename":"CollectionPublication","publishedAt":"2023-04-20T11:12:24Z","__parentId":"gid:\/\/shopify\/Collection\/273278566589"}\n""" + + +@pytest.fixture +def transactions_jsonl_content_example(): + return ( + dumps( + { + "__typename": "Order", + "id": "gid://shopify/Order/1", + "currency": "USD", + "transactions": [ + { + "id": "gid://shopify/OrderTransaction/1", + "errorCode": None, + "parentTransaction": {"parentId": "gid://shopify/ParentOrderTransaction/0"}, + "test": True, + "kind": "SALE", + "amount": "102.00", + "receipt": '{"paid_amount":"102.00"}', + "gateway": "test", + "authorization": "1234", + "createdAt": "2030-07-02T07:51:49Z", + "status": "SUCCESS", + "processedAt": "2030-07-02T07:51:49Z", + "totalUnsettledSet": { + "presentmentMoney": {"amount": "0.0", "currency": "USD"}, + "shopMoney": {"amount": "0.0", "currency": "USD"}, + }, + "paymentId": "some_payment_id.1", + "paymentDetails": { + "avsResultCode": None, + "cvvResultCode": None, + "creditCardBin": "1", + "creditCardCompany": "Test", + "creditCardNumber": "•••• •••• •••• 1", + "creditCardName": "Test Gateway", + "creditCardWallet": None, + "creditCardExpirationYear": 2023, + "creditCardExpirationMonth": 11, + }, + } + ], + } + ) + + "\n" + ) + + +@pytest.fixture +def metafield_parse_response_expected_result(): + return { + "id": 123, + "admin_graphql_api_id": "gid://shopify/Metafield/123", + "owner_id": 1234567, + "owner_resource": "order", + "shop_url": "test_shop", + "created_at": "2023-01-01T01:01:01+00:00", + "updated_at": "2023-01-01T01:01:01+00:00", + } + + +@pytest.fixture +def fulfillment_orders_response_expected_result(): + return { + "id": 2, + "assigned_location": { + "address1": "Test", + "address2": None, + "city": "Test", + "country_code": "Test", + "name": "Test", + "phone": "", + "province": None, + "zip": "00000", + "location_id": 123, + }, + "destination": { + "id": 777, + }, + "delivery_method": { + "id": 123, + "method_type": "SHIPPING", + "min_delivery_date_time": "2023-04-13T12:00:00+00:00", + "max_delivery_date_time": "2023-04-13T12:00:00+00:00", + }, + "fulfill_at": "2023-04-13T12:00:00+00:00", + "fulfill_by": None, + "international_duties": None, + "fulfillment_holds": [], + "created_at": "2023-04-13T12:09:45+00:00", + "updated_at": "2023-04-13T12:09:46+00:00", + "request_status": "UNSUBMITTED", + "status": "CLOSED", + "supported_actions": [], + "shop_id": None, + "order_id": 1, + "assigned_location_id": 123, + "line_items": [ + { + "id": 3, + "inventory_item_id": 33, + "shop_id": None, + "fulfillment_order_id": 2, + "quantity": 1, + "line_item_id": 31, + "fulfillable_quantity": 0, + "variant_id": 333, + }, + ], + "merchant_requests": [{"id": 333, "message": None, "kind": "FULFILLMENT_REQUEST", "request_options": {"notify_customer": True}}], + "admin_graphql_api_id": "gid://shopify/FulfillmentOrder/2", + "shop_url": "test_shop", + } + + +@pytest.fixture +def inventory_items_response_expected_result(): + return [ + { + "id": 44871665713341, + "country_code_of_origin": None, + "harmonized_system_code": None, + "province_code_of_origin": None, + "updated_at": "2023-04-14T10:29:27+00:00", + "created_at": "2023-04-14T10:29:27+00:00", + "sku": "", + "tracked": True, + "requires_shipping": False, + "admin_graphql_api_id": "gid://shopify/InventoryItem/44871665713341", + "cost": None, + "country_harmonized_system_codes": [], + "shop_url": "test_shop", + }, + { + "id": 45419395743933, + "country_code_of_origin": "UA", + "harmonized_system_code": "330510", + "province_code_of_origin": None, + "updated_at": "2023-12-11T10:37:41+00:00", + "created_at": "2023-12-11T10:37:41+00:00", + "sku": "123", + "tracked": True, + "requires_shipping": True, + "admin_graphql_api_id": "gid://shopify/InventoryItem/45419395743933", + "cost": 29.0, + "country_harmonized_system_codes": [], + "shop_url": "test_shop", + }, + ] + + +@pytest.fixture +def customer_address_parse_response_expected_result(): + return [ + { + "address1": "My Best Accent", + "address2": "", + "city": "Fair Lawn", + "country": "United States", + "country_code": "US", + "company": "Test Company", + "first_name": "New Test", + "id": 123, + "last_name": "Customer", + "name": "New Test Customer", + "phone": "", + "province": "New Jersey", + "province_code": "NJ", + "zip": "07410", + "customer_id": 123, + "country_name": "United States", + "default": True, + "updated_at": "2023-04-24T13:53:48+00:00", + "shop_url": "test_shop" + }, + { + "address1": None, + "address2": None, + "city": None, + "country": None, + "country_code": None, + "company": None, + "first_name": "MArcos", + "id": 456, + "last_name": "Millnitz", + "name": "MArcos Millnitz", + "phone": None, + "province": None, + "province_code": None, + "zip": None, + "customer_id": 456, + "country_name": None, + "default": True, + "updated_at": "2023-07-11T20:07:45+00:00", + "shop_url": "test_shop" + } +] + + +@pytest.fixture +def inventory_levels_response_expected_result(): + return [ + { + "id": "63590301885|42185200631997", + "available": 15, + "updated_at": "2023-04-13T12:00:55+00:00", + "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185200631997", + "inventory_item_id": 42185200631997, + "location_id": 63590301885, + "shop_url": "test_shop", + }, + { + "id": "63590301885|42185218719933", + "available": 8, + "updated_at": "2023-04-13T12:09:45+00:00", + "admin_graphql_api_id": "gid://shopify/InventoryLevel/97912455357?inventory_item_id=42185218719933", + "inventory_item_id": 42185218719933, + "location_id": 63590301885, + "shop_url": "test_shop", + }, + ] + + +@pytest.fixture +def discount_codes_response_expected_result(): + return [ + { + "usage_count": 0, + "code": "TEST", + "id": 11545139282109, + "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/11545139282109", + "price_rule_id": 945205379261, + "updated_at": "2023-12-07T11:40:44+00:00", + "created_at": "2021-07-08T12:40:37+00:00", + "summary": "Free shipping on all products • Minimum purchase of $1.00 • For all countries", + "discount_type": "SHIPPING", + "shop_url": "test_shop", + }, + { + "usage_count": 0, + "code": "TEST2", + "id": 13175793582269, + "admin_graphql_api_id": "gid://shopify/DiscountRedeemCode/13175793582269", + "price_rule_id": 945205379261, + "updated_at": "2023-12-07T11:40:44+00:00", + "created_at": "2021-07-08T12:40:37+00:00", + "summary": "Free shipping on all products • Minimum purchase of $1.00 • For all countries", + "discount_type": "SHIPPING", + "shop_url": "test_shop", + }, + ] + + +@pytest.fixture +def collections_response_expected_result(): + return [ + { + "id": 270889287869, + "handle": "frontpage", + "title": "Home page", + "updated_at": "2023-09-05T14:06:59+00:00", + "body_html": "updated_mon_24.04.2023", + "sort_order": "BEST_SELLING", + "template_suffix": "", + "products_count": 1, + "admin_graphql_api_id": "gid://shopify/Collection/270889287869", + "published_at": "2021-06-23T01:00:25+00:00", + "shop_url": "test_shop", + }, + { + "id": 273278566589, + "handle": "test-collection", + "title": "Test Collection", + "updated_at": "2023-09-05T14:12:04+00:00", + "body_html": "updated_mon_24.04.2023", + "sort_order": "BEST_SELLING", + "template_suffix": "", + "products_count": 26, + "admin_graphql_api_id": "gid://shopify/Collection/273278566589", + "published_at": "2021-07-19T14:02:54+00:00", + "shop_url": "test_shop", + }, + ] + + +@pytest.fixture +def transactions_response_expected_result(): + return { + "id": 1, + "error_code": None, + "test": True, + "kind": "SALE", + "amount": 102.0, + "receipt": '{"paid_amount":"102.00"}', + "gateway": "test", + "authorization": "1234", + "created_at": "2030-07-02T07:51:49+00:00", + "status": "SUCCESS", + "processed_at": "2030-07-02T07:51:49+00:00", + "total_unsettled_set": {"presentment_money": {"amount": 0.0, "currency": "USD"}, "shop_money": {"amount": 0.0, "currency": "USD"}}, + "payment_id": "some_payment_id.1", + "payment_details": { + "avs_result_code": None, + "cvv_result_code": None, + "credit_card_bin": "1", + "credit_card_company": "Test", + "credit_card_number": "•••• •••• •••• 1", + "credit_card_name": "Test Gateway", + "credit_card_wallet": None, + "credit_card_expiration_year": 2023, + "credit_card_expiration_month": 11, + }, + "order_id": 1, + "currency": "USD", + "admin_graphql_api_id": "gid://shopify/OrderTransaction/1", + "parent_id": 0, + "shop_url": "test_shop", + } diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_job.py b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_job.py new file mode 100644 index 000000000000..fa5d50cd0bee --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_job.py @@ -0,0 +1,265 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import pytest +import requests +from source_shopify.shopify_graphql.bulk.exceptions import ShopifyBulkExceptions +from source_shopify.shopify_graphql.bulk.job import ShopifyBulkStatus +from source_shopify.streams.streams import ( + Collections, + CustomerAddress, + DiscountCodes, + FulfillmentOrders, + InventoryItems, + InventoryLevels, + MetafieldOrders, + TransactionsGraphql, +) + + +@pytest.mark.parametrize( + "bulk_job_response, expected_len", + [ + ("bulk_error", 1), + ("bulk_unknown_error", 1), + ("bulk_no_errors", 0), + ], +) +def test_check_for_errors(request, requests_mock, bulk_job_response, expected_len, auth_config) -> None: + stream = MetafieldOrders(auth_config) + requests_mock.get(stream.job_manager.base_url, json=request.getfixturevalue(bulk_job_response)) + test_response = requests.get(stream.job_manager.base_url) + test_errors = stream.job_manager.job_check_for_errors(test_response) + assert len(test_errors) == expected_len + + +def test_get_errors_from_response_invalid_response(auth_config) -> None: + expected = "Couldn't check the `response` for `errors`" + stream = MetafieldOrders(auth_config) + response = requests.Response() + response.status_code = 404 + response.url = "https://example.com/invalid" + with pytest.raises(ShopifyBulkExceptions.BulkJobBadResponse) as error: + stream.job_manager.job_check_for_errors(response) + assert expected in repr(error.value) + + +@pytest.mark.parametrize( + "bulk_job_response, expected", + [ + ("bulk_error_with_concurrent_job", True), + ("bulk_successful_response", False), + ("bulk_error", False), + ], +) +def test_has_running_concurrent_job(request, requests_mock, bulk_job_response, auth_config, expected) -> None: + stream = MetafieldOrders(auth_config) + requests_mock.get(stream.job_manager.base_url, json=request.getfixturevalue(bulk_job_response)) + test_response = requests.get(stream.job_manager.base_url) + test_errors = stream.job_manager.job_check_for_errors(test_response) + assert stream.job_manager.has_running_concurrent_job(test_errors) == expected + + +@pytest.mark.parametrize( + "bulk_job_response, expected", + [ + ("bulk_successful_response", "gid://shopify/BulkOperation/4046733967549"), + ("bulk_error", None), + ("bulk_successful_response_with_no_id", None), + ], +) +def test_job_get_id(request, requests_mock, bulk_job_response, auth_config, expected) -> None: + stream = MetafieldOrders(auth_config) + requests_mock.get(stream.job_manager.base_url, json=request.getfixturevalue(bulk_job_response)) + test_response = requests.get(stream.job_manager.base_url) + assert stream.job_manager.job_get_id(test_response) == expected + + +def test_job_state_completed(auth_config) -> None: + stream = MetafieldOrders(auth_config) + stream.job_manager.job_state = ShopifyBulkStatus.COMPLETED.value + assert stream.job_manager.job_completed() == True + + +@pytest.mark.parametrize( + "bulk_job_response, concurrent_max_retry, error_type, expected", + [ + # method should return this response fixture, once retried. + ("bulk_successful_completed_response", 2, None, "gid://shopify/BulkOperation/4046733967549"), + # method should raise AirbyteTracebackException, because the concurrent BULK Job is in progress + ( + "bulk_error_with_concurrent_job", + 1, + ShopifyBulkExceptions.BulkJobConcurrentError, + "The BULK Job couldn't be created at this time, since another job is running", + ), + ], + ids=[ + "regular concurrent request", + "max atttempt reached", + ] +) +def test_job_retry_on_concurrency(request, requests_mock, bulk_job_response, concurrent_max_retry, error_type, auth_config, expected) -> None: + stream = MetafieldOrders(auth_config) + # patching concurent settings + stream.job_manager.concurrent_max_retry = concurrent_max_retry + stream.job_manager.concurrent_interval_sec = 1 + requests_mock.get(stream.job_manager.base_url, json=request.getfixturevalue(bulk_job_response)) + if error_type: + with pytest.raises(error_type) as error: + stream.job_manager.job_retry_on_concurrency(requests.get(stream.job_manager.base_url).request) + assert expected in repr(error.value) + else: + result = stream.job_manager.job_retry_on_concurrency(requests.get(stream.job_manager.base_url).request) + assert stream.job_manager.job_get_id(result) == expected + + + +@pytest.mark.parametrize( + "job_response, error_type, patch_healthcheck, expected", + [ + ( + "bulk_job_completed_response", + None, + False, + "bulk-123456789.jsonl", + ), + ("bulk_job_failed_response", ShopifyBulkExceptions.BulkJobFailed, False, "exited with FAILED"), + ("bulk_job_timeout_response", ShopifyBulkExceptions.BulkJobTimout, False, "exited with TIMEOUT"), + ("bulk_job_access_denied_response", ShopifyBulkExceptions.BulkJobAccessDenied, False, "exited with ACCESS_DENIED"), + ("bulk_successful_response_with_errors", ShopifyBulkExceptions.BulkJobUnknownError, True, "Could not validate the status of the BULK Job"), + ], + ids=[ + "completed", + "failed", + "timeout", + "access_denied", + "success with errors (edge)", + ], +) +def test_job_check(mocker, request, requests_mock, job_response, auth_config, error_type, patch_healthcheck, expected) -> None: + stream = MetafieldOrders(auth_config) + # modify the sleep time for the test + stream.job_manager.concurrent_max_retry = 1 + stream.job_manager.concurrent_interval_sec = 1 + stream.job_manager.job_check_interval_sec = 1 + # get job_id from FIXTURE + job_id = request.getfixturevalue(job_response).get("data", {}).get("node", {}).get("id") + # patching the method to get the right ID checks + if job_id: + mocker.patch("source_shopify.shopify_graphql.bulk.job.ShopifyBulkManager.job_get_id", value=job_id) + if patch_healthcheck: + mocker.patch("source_shopify.shopify_graphql.bulk.job.ShopifyBulkManager.job_healthcheck", value=job_response) + # mocking the response for STATUS CHECKS + requests_mock.post(stream.job_manager.base_url, json=request.getfixturevalue(job_response)) + test_job_status_response = requests.post(stream.job_manager.base_url) + job_result_url = test_job_status_response.json().get("data", {}).get("node", {}).get("url") + if error_type: + with pytest.raises(error_type) as error: + stream.job_manager.job_check(test_job_status_response) + assert expected in repr(error.value) + else: + if job_result_url: + # mocking the nested request call to retrieve the data from result URL + requests_mock.get(job_result_url, json=request.getfixturevalue(job_response)) + result = stream.job_manager.job_check(test_job_status_response) + assert expected == result + + +@pytest.mark.parametrize( + "job_response, expected", + [ + ("bulk_job_created_response", ShopifyBulkStatus.CREATED.value), + ("bulk_job_running_response", ShopifyBulkStatus.RUNNING.value), + ("bulk_job_running_response_without_id", ShopifyBulkStatus.RUNNING.value), + ], + ids=[ + "created", + "running", + "running_no_id (edge)", + ], +) +def test_job_check_with_running_scenario(request, requests_mock, job_response, auth_config, expected) -> None: + stream = MetafieldOrders(auth_config) + # modify the sleep time for the test + stream.job_manager.job_check_interval_sec = 0 + # get job_id from FIXTURE + job_id = request.getfixturevalue(job_response).get("data", {}).get("node", {}).get("id") + # mocking the response for STATUS CHECKS + requests_mock.post(stream.job_manager.base_url, json=request.getfixturevalue(job_response)) + test_job_status_response = requests.post(stream.job_manager.base_url) + job_result_url = test_job_status_response.json().get("data", {}).get("node", {}).get("url") + # test the state of the job isn't assigned + assert stream.job_manager.job_state == None + + # mocking the nested request call to retrieve the data from result URL + stream.job_manager.job_id = job_id + requests_mock.get(job_result_url, json=request.getfixturevalue(job_response)) + + # calling the sceario processing + stream.job_manager.job_track_running() + assert stream.job_manager.job_state == expected + + + +def test_job_read_file_invalid_filename(mocker, auth_config) -> None: + stream = MetafieldOrders(auth_config) + expected = "An error occured while producing records from BULK Job result" + # patching the method to get the filename + mocker.patch("source_shopify.shopify_graphql.bulk.record.ShopifyBulkRecord.produce_records", side_effect=Exception) + with pytest.raises(ShopifyBulkExceptions.BulkRecordProduceError) as error: + list(stream.record_producer.read_file("test.jsonl")) + + assert expected in repr(error.value) + + +@pytest.mark.parametrize( + "stream, json_content_example, expected", + [ + (CustomerAddress, "customer_address_jsonl_content_example", "customer_address_parse_response_expected_result"), + (MetafieldOrders, "metafield_jsonl_content_example", "metafield_parse_response_expected_result"), + (FulfillmentOrders, "filfillment_order_jsonl_content_example", "fulfillment_orders_response_expected_result"), + (DiscountCodes, "discount_codes_jsonl_content_example", "discount_codes_response_expected_result"), + (Collections, "collections_jsonl_content_example", "collections_response_expected_result"), + (TransactionsGraphql, "transactions_jsonl_content_example", "transactions_response_expected_result"), + (InventoryItems, "inventory_items_jsonl_content_example", "inventory_items_response_expected_result"), + (InventoryLevels, "inventory_levels_jsonl_content_example", "inventory_levels_response_expected_result"), + ], + ids=[ + "CustomerAddress", + "MetafieldOrders", + "FulfillmentOrders", + "DiscountCodes", + "Collections", + "TransactionsGraphql", + "InventoryItems", + "InventoryLevels", + ], +) +def test_bulk_stream_parse_response( + request, + requests_mock, + bulk_job_completed_response, + stream, + json_content_example, + expected, + auth_config, +) -> None: + stream = stream(auth_config) + # get the mocked job_result_url + test_result_url = bulk_job_completed_response.get("data").get("node").get("url") + # mocking the result url with jsonl content + requests_mock.post(stream.job_manager.base_url, json=bulk_job_completed_response) + # getting mock response + test_bulk_response: requests.Response = requests.post(stream.job_manager.base_url) + # mocking nested api call to get data from result url + requests_mock.get(test_result_url, text=request.getfixturevalue(json_content_example)) + # parsing result from completed job + test_records = list(stream.parse_response(test_bulk_response)) + expected_result = request.getfixturevalue(expected) + if isinstance(expected_result, dict): + assert test_records == [expected_result] + elif isinstance(expected_result, list): + assert test_records == expected_result diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_query.py b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_query.py new file mode 100644 index 000000000000..9b9bb8da0873 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_query.py @@ -0,0 +1,209 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import pytest +from graphql_query import Argument, Field, Operation, Query +from source_shopify.shopify_graphql.bulk.query import ( + InventoryLevel, + MetafieldCustomer, + MetafieldProductImage, + ShopifyBulkQuery, + ShopifyBulkTemplates, +) + + +def test_query_status() -> None: + expected = """query { + node(id: "gid://shopify/BulkOperation/4047052112061") { + ... on BulkOperation { + id + status + errorCode + objectCount + fileSize + url + partialDataUrl + } + } + }""" + + input_job_id = "gid://shopify/BulkOperation/4047052112061" + template = ShopifyBulkTemplates.status(input_job_id) + assert repr(template) == repr(expected) + + +def test_bulk_query_prepare() -> None: + expected = '''mutation { + bulkOperationRunQuery( + query: """ + {some_query} + """ + ) { + bulkOperation { + id + status + } + userErrors { + field + message + } + } + }''' + + input_query_from_slice = "{some_query}" + template = ShopifyBulkTemplates.prepare(input_query_from_slice) + assert repr(template) == repr(expected) + + +@pytest.mark.parametrize( + "query_name, fields, filter_field, start, end, expected", + [ + ( + "test_root", + ["test_field1", "test_field2"], + "updated_at", + "2023-01-01", + "2023-01-02", + Query( + name='test_root', + arguments=[ + Argument(name="query", value=f"\"updated_at:>'2023-01-01' AND updated_at:<='2023-01-02'\""), + ], + fields=[Field(name='edges', fields=[Field(name='node', fields=["test_field1", "test_field2"])])] + ) + ) + ], + ids=["simple query with filter and sort"] +) +def test_base_build_query(query_name, fields, filter_field, start, end, expected) -> None: + """ + Expected result rendered: + ''' + { + test_root(query: "updated_at:>'2023-01-01' AND updated_at:<='2023-01-02'") { + edges { + node { + id + test_field1 + test_field2 + } + } + } + ''' + """ + + + builder = ShopifyBulkQuery(shop_id=0) + filter_query = f"{filter_field}:>'{start}' AND {filter_field}:<='{end}'" + built_query = builder.build(query_name, fields, filter_query) + assert expected.render() == built_query.render() + + +@pytest.mark.parametrize( + "query_class, filter_field, start, end, expected", + [ + ( + MetafieldCustomer, + "updated_at", + "2023-01-01", + "2023-01-02", + Operation( + type="", + queries=[ + Query( + name='customers', + arguments=[ + Argument(name="query", value=f"\"updated_at:>='2023-01-01' AND updated_at:<='2023-01-02'\""), + Argument(name="sortKey", value="UPDATED_AT"), + ], + fields=[Field(name='edges', fields=[Field(name='node', fields=['__typename', 'id', Field(name="metafields", fields=[Field(name="edges", fields=[Field(name="node", fields=["__typename", "id", "namespace", "value", "key", "description", "createdAt", "updatedAt", "type"])])])])])] + ) + ] + ), + ), + ( + MetafieldProductImage, + "updated_at", + "2023-01-01", + "2023-01-02", + Operation( + type="", + queries=[ + Query( + name='products', + arguments=[ + Argument(name="query", value=f"\"updated_at:>='2023-01-01' AND updated_at:<='2023-01-02'\""), + Argument(name="sortKey", value="UPDATED_AT"), + ], + fields=[Field(name='edges', fields=[Field(name='node', fields=['__typename','id',Field(name="images", fields=[Field(name="edges", fields=[Field(name="node", fields=["__typename", "id", Field(name="metafields", fields=[Field(name="edges", fields=[Field(name="node", fields=["__typename", "id", "namespace", "value", "key", "description", "createdAt", "updatedAt", "type"])])])])])])])])] + ) + ] + ), + ), + ( + InventoryLevel, + "updated_at", + "2023-01-01", + "2023-01-02", + Operation( + type="", + queries=[ + Query( + name='locations', + arguments=[ + Argument(name="includeLegacy", value="true"), + Argument(name="includeInactive", value="true"), + ], + fields=[ + Field( + name='edges', + fields=[ + Field( + name='node', + fields=[ + '__typename', + 'id', + Query( + name="inventoryLevels", + arguments=[ + Argument(name="query", value=f"\"updated_at:>='2023-01-01' AND updated_at:<='2023-01-02'\""), + ], + fields=[ + Field( + name="edges", + fields=[ + Field( + name="node", + fields=[ + "__typename", + "id", + Field(name="available"), + Field(name="item", fields=[Field(name="id", alias="inventory_item_id")]), + Field(name="updatedAt") + ] + ) + ] + ) + ] + ) + ] + ) + ] + ) + ] + ) + ] + ), + ), + ], + ids=[ + "MetafieldCustomers query with 1 query_path(str)", + "MetafieldProductImages query with composite quey_path(List[2])", + "InventoryLevel query", + ] +) +def test_bulk_query(query_class, filter_field, start, end, expected) -> None: + stream = query_class(shop_id=0) + assert stream.get(filter_field, start, end) == expected.render() \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_record.py b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_record.py new file mode 100644 index 000000000000..2c163004cb38 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_record.py @@ -0,0 +1,198 @@ +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. + + +import pytest +from source_shopify.shopify_graphql.bulk.query import ShopifyBulkQuery +from source_shopify.shopify_graphql.bulk.record import ShopifyBulkRecord + + +@pytest.mark.parametrize( + "record, expected", + [ + ( + {"id": "gid://shopify/Order/19435458986123"}, + {"id": 19435458986123, "admin_graphql_api_id": "gid://shopify/Order/19435458986123"}, + ), + ({"id": 123}, {"id": 123}), + ], +) +def test_record_resolve_id(record, expected) -> None: + bulk_query = ShopifyBulkQuery(shop_id=0) + assert ShopifyBulkRecord(bulk_query).record_resolve_id(record) == expected + + +@pytest.mark.parametrize( + "record, types, expected", + [ + ({"__typename": "Order", "id": "gid://shopify/Order/19435458986123"}, ["Test", "Order"], True), + ({"__typename": "Test", "id": "gid://shopify/Order/19435458986123"}, "Other", False), + ({}, "Other", False), + ], +) +def test_check_type(record, types, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + assert ShopifyBulkRecord(query).check_type(record, types) == expected + + +@pytest.mark.parametrize( + "record, expected", + [ + ( + { + "id": "gid://shopify/Metafield/123", + "__parentId": "gid://shopify/Order/102030", + }, + { + "id": 123, + "admin_graphql_api_id": "gid://shopify/Metafield/123", + "__parentId": "gid://shopify/Order/102030", + }, + ) + ], +) +def test_record_resolver(record, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + record_instance = ShopifyBulkRecord(query) + assert record_instance.record_resolve_id(record) == expected + + +@pytest.mark.parametrize( + "record, expected", + [ + ( + {"id": "gid://shopify/Order/1234567890", "__typename": "Order"}, + {"id": "gid://shopify/Order/1234567890"}, + ), + ], +) +def test_record_new(record, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + record_instance = ShopifyBulkRecord(query) + record_instance.record_new(record) + assert record_instance.buffer == [expected] + + +@pytest.mark.parametrize( + "records_from_jsonl, record_components, expected", + [ + ( + [ + {"__typename": "NewRecord", "id": "gid://shopify/NewRecord/1234567890", "name": "new_record"}, + {"__typename": "RecordComponent", "id": "gid://shopify/RecordComponent/1234567890", "name": "new_component"}, + ], + {"new_record": "NewRecord", "record_components": ["RecordComponent"]}, + [ + { + "id": "gid://shopify/NewRecord/1234567890", + "name": "new_record", + "record_components": { + "RecordComponent": [ + { + "id": "gid://shopify/RecordComponent/1234567890", + "name": "new_component", + }, + ] + }, + } + ], + ), + ], + ids=["add_component"], +) +def test_record_new_component(records_from_jsonl, record_components, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + record_instance = ShopifyBulkRecord(query) + record_instance.components = record_components.get("record_components") + # register new record first + record_instance.record_new(records_from_jsonl[0]) + assert len(record_instance.buffer) > 0 + # check the components placeholder was created for new record registered + assert "record_components" in record_instance.buffer[-1].keys() + # register record component + record_instance.record_new_component(records_from_jsonl[1]) + # check the component was proccessed + assert len(record_instance.buffer[-1]["record_components"]["RecordComponent"]) > 0 + # general check + assert record_instance.buffer == expected + + +@pytest.mark.parametrize( + "buffered_record, expected", + [ + ( + { + "id": "gid://shopify/NewRecord/1234567890", + "name": "new_record", + "record_components": { + "RecordComponent": [ + { + "id": "gid://shopify/RecordComponent/1234567890", + "name": "new_component", + } + ] + }, + }, + [ + { + "id": 1234567890, + "name": "new_record", + "record_components": { + "RecordComponent": [ + { + "id": "gid://shopify/RecordComponent/1234567890", + "name": "new_component", + }, + ] + }, + "admin_graphql_api_id": "gid://shopify/NewRecord/1234567890", + } + ], + ), + ], +) +def test_buffer_flush(buffered_record, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + record_instance = ShopifyBulkRecord(query) + # populate the buffer with record + record_instance.buffer.append(buffered_record) + assert list(record_instance.buffer_flush()) == expected + + +@pytest.mark.parametrize( + "records_from_jsonl, record_composition, expected", + [ + ( + [ + {"__typename": "NewRecord", "id": "gid://shopify/NewRecord/1234567890", "name": "new_record"}, + {"__typename": "RecordComponent", "id": "gid://shopify/RecordComponent/1234567890", "name": "new_component"}, + ], + {"new_record": "NewRecord", "record_components": ["RecordComponent"]}, + [ + { + "id": "gid://shopify/NewRecord/1234567890", + "name": "new_record", + "record_components": { + "RecordComponent": [ + { + "id": "gid://shopify/RecordComponent/1234567890", + "name": "new_component", + }, + ] + }, + } + ], + ), + ], + ids=["test_compose"], +) +def test_record_compose(records_from_jsonl, record_composition, expected) -> None: + query = ShopifyBulkQuery(shop_id=0) + # query.record_composition = record_composition + record_instance = ShopifyBulkRecord(query) + record_instance.composition = record_composition + record_instance.components = record_composition.get("record_components") + # process read jsonl records + for record in records_from_jsonl: + list(record_instance.record_compose(record)) + + assert record_instance.buffer == expected diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_tools.py b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_tools.py new file mode 100644 index 000000000000..ba7e0474f494 --- /dev/null +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/graphql_bulk/test_tools.py @@ -0,0 +1,54 @@ +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. + + +import pytest +from source_shopify.shopify_graphql.bulk.exceptions import ShopifyBulkExceptions +from source_shopify.shopify_graphql.bulk.tools import BulkTools + + +def test_camel_to_snake() -> None: + assert BulkTools.camel_to_snake("camelCase") == "camel_case" + assert BulkTools.camel_to_snake("snake_case") == "snake_case" + assert BulkTools.camel_to_snake("PascalCase") == "pascal_case" + + +@pytest.mark.parametrize( + "job_result_url, error_type, expected", + [ + ( + "https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/?GoogleAccessId=assets-us-prod%40shopify-tiers.iam.gserviceaccount.com&Expires=1705508208&Signature=%3D%3D&response-content-disposition=attachment%3B+filename%3D%22bulk-4147374162109.jsonl%22%3B+filename%2A%3DUTF-8%27%27bulk-4147374162109.jsonl&response-content-type=application%2Fjsonl", + None, + "bulk-4147374162109.jsonl", + ), + ( + "https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/?GoogleAccessId=assets-us-prod%40shopify-tiers.iam.gserviceaccount.com&Expires=1705508208", + ShopifyBulkExceptions.BulkJobResultUrlError, + "Could not extract the `filename` from `result_url` provided", + ), + ], + ids=["success", "error"], +) +def test_filename_from_url(job_result_url, error_type, expected) -> None: + if error_type: + with pytest.raises(error_type) as error: + BulkTools.filename_from_url(job_result_url) + assert expected in repr(error.value) + else: + assert BulkTools.filename_from_url(job_result_url) == expected + + +def test_from_iso8601_to_rfc3339() -> None: + record = {"date": "2023-01-01T15:00:00Z"} + assert BulkTools.from_iso8601_to_rfc3339(record, "date") == "2023-01-01T15:00:00+00:00" + + +def test_fields_names_to_snake_case() -> None: + dict_input = {"camelCase": "value", "snake_case": "value", "__parentId": "value"} + expected_output = {"camel_case": "value", "snake_case": "value", "__parentId": "value"} + assert BulkTools().fields_names_to_snake_case(dict_input) == expected_output + + +def test_resolve_str_id() -> None: + assert BulkTools.resolve_str_id("123") == 123 + assert BulkTools.resolve_str_id("456", str) == "456" + assert BulkTools.resolve_str_id(None) is None diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/test_cached_stream_state.py b/airbyte-integrations/connectors/source-shopify/unit_tests/test_cached_stream_state.py index 031e7871e8ef..80cc6115c449 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/test_cached_stream_state.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/test_cached_stream_state.py @@ -4,7 +4,7 @@ import pytest -from source_shopify.source import OrderRefunds, Orders +from source_shopify.streams.streams import OrderRefunds, Orders from source_shopify.utils import EagerlyCachedStreamState as stream_state_cache # Define the Stream instances for the tests diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/test_deleted_events_stream.py b/airbyte-integrations/connectors/source-shopify/unit_tests/test_deleted_events_stream.py index 6dde83e179de..126d28b7e66d 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/test_deleted_events_stream.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/test_deleted_events_stream.py @@ -5,7 +5,8 @@ import pytest from source_shopify.auth import ShopifyAuthenticator -from source_shopify.source import Products, ShopifyDeletedEventsStream +from source_shopify.streams.base_streams import ShopifyDeletedEventsStream +from source_shopify.streams.streams import Products @pytest.fixture @@ -21,7 +22,7 @@ def config(basic_config): (Products, "products.json", "events.json"), ], ) -def test_path(stream, expected_main_path, expected_events_path, config): +def test_path(stream, expected_main_path, expected_events_path, config) -> None: stream = stream(config) main_path = stream.path() events_path = stream.deleted_events.path() @@ -35,7 +36,7 @@ def test_path(stream, expected_main_path, expected_events_path, config): (Products, {}), ], ) -def test_get_json_schema(stream, expected_events_schema, config): +def test_get_json_schema(stream, expected_events_schema, config) -> None: stream = stream(config) schema = stream.deleted_events.get_json_schema() # no schema is expected @@ -48,7 +49,7 @@ def test_get_json_schema(stream, expected_events_schema, config): (Products, "events", "id", "deleted_at"), ], ) -def test_has_correct_instance_vars(stream, expected_data_field, expected_pk, expected_cursor_field, config): +def test_has_correct_instance_vars(stream, expected_data_field, expected_pk, expected_cursor_field, config) -> None: stream = stream(config) assert stream.deleted_events.data_field == expected_data_field assert stream.deleted_events.primary_key == expected_pk @@ -61,7 +62,7 @@ def test_has_correct_instance_vars(stream, expected_data_field, expected_pk, exp (Products, None), ], ) -def test_has_no_availability_strategy(stream, expected, config): +def test_has_no_availability_strategy(stream, expected, config) -> None: stream = stream(config) # no availability_strategy is expected assert stream.deleted_events.availability_strategy is expected @@ -103,11 +104,11 @@ def test_has_no_availability_strategy(stream, expected, config): ), ], ) -def test_read_deleted_records(stream, requests_mock, deleted_records_json, expected, config, mocker): +def test_read_deleted_records(stream, requests_mock, deleted_records_json, expected, config, mocker) -> None: stream = stream(config) deleted_records_url = stream.url_base + stream.deleted_events.path() requests_mock.get(deleted_records_url, json=deleted_records_json) - mocker.patch("source_shopify.source.IncrementalShopifyStreamWithDeletedEvents.read_records", return_value=deleted_records_json) + mocker.patch("source_shopify.streams.base_streams.IncrementalShopifyStreamWithDeletedEvents.read_records", return_value=deleted_records_json) assert list(stream.read_records(sync_mode=None)) == expected @@ -143,7 +144,7 @@ def test_read_deleted_records(stream, requests_mock, deleted_records_json, expec ), ], ) -def test_produce_deleted_records_from_events(stream, input, expected, config): +def test_produce_deleted_records_from_events(stream, input, expected, config) -> None: stream = stream(config) result = stream.deleted_events.produce_deleted_records_from_events(input) assert list(result) == expected @@ -178,7 +179,7 @@ def test_produce_deleted_records_from_events(stream, input, expected, config): ), ], ) -def test_request_params(config, stream, stream_state, next_page_token, expected_stream_params, expected_deleted_params): +def test_request_params(config, stream, stream_state, next_page_token, expected_stream_params, expected_deleted_params) -> None: stream = stream(config) assert stream.request_params(stream_state=stream_state, next_page_token=next_page_token) == expected_stream_params assert stream.deleted_events.request_params(stream_state=stream_state, next_page_token=next_page_token) == expected_deleted_params @@ -190,7 +191,7 @@ def test_request_params(config, stream, stream_state, next_page_token, expected_ (Products, ShopifyDeletedEventsStream), ], ) -def test_deleted_events_instance(stream, config, expected): +def test_deleted_events_instance(stream, config, expected) -> None: stream = stream(config) assert isinstance(stream.deleted_events, expected) @@ -201,7 +202,7 @@ def test_deleted_events_instance(stream, config, expected): (Products, ""), ], ) -def test_default_deleted_state_comparison_value(stream, config, expected): +def test_default_deleted_state_comparison_value(stream, config, expected) -> None: stream = stream(config) assert stream.default_deleted_state_comparison_value == expected @@ -239,6 +240,6 @@ def test_default_deleted_state_comparison_value(stream, config, expected): ), ], ) -def test_get_updated_state(config, stream, last_record, current_state, expected): +def test_get_updated_state(config, stream, last_record, current_state, expected) -> None: stream = stream(config) assert stream.get_updated_state(current_state, last_record) == expected diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/test_graphql_products.py b/airbyte-integrations/connectors/source-shopify/unit_tests/test_graphql_products.py index d1a9f02de29b..a6c99f9c3c44 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/test_graphql_products.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/test_graphql_products.py @@ -1,7 +1,7 @@ # Copyright (c) 2023 Airbyte, Inc., all rights reserved. import pytest -from source_shopify.graphql import get_query_products +from source_shopify.shopify_graphql.graphql import get_query_products @pytest.mark.parametrize( diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/test_source.py b/airbyte-integrations/connectors/source-shopify/unit_tests/test_source.py index 1f4f7bb1d0e9..e4f07f314761 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/test_source.py @@ -7,7 +7,8 @@ import pytest from source_shopify.auth import ShopifyAuthenticator -from source_shopify.source import ( +from source_shopify.source import SourceShopify +from source_shopify.streams.streams import ( AbandonedCheckouts, Articles, Blogs, @@ -41,14 +42,14 @@ Products, ProductVariants, Shop, - SourceShopify, TenderTransactions, Transactions, + TransactionsGraphql, ) @pytest.fixture -def config(basic_config): +def config(basic_config) -> dict: basic_config["start_date"] = "2020-11-01" basic_config["authenticator"] = ShopifyAuthenticator(basic_config) return basic_config @@ -61,18 +62,22 @@ def config(basic_config): (Blogs, None, "blogs.json"), (MetafieldBlogs, {"id": 123}, "blogs/123/metafields.json"), (MetafieldArticles, {"id": 123}, "articles/123/metafields.json"), - (MetafieldCustomers, {"id": 123}, "customers/123/metafields.json"), - (MetafieldOrders, {"id": 123}, "orders/123/metafields.json"), - (MetafieldDraftOrders, {"id": 123}, "draft_orders/123/metafields.json"), - (MetafieldProducts, {"id": 123}, "products/123/metafields.json"), - (MetafieldProductVariants, {"variants": 123}, "variants/123/metafields.json"), + # GraphQL Bulk Streams + (MetafieldCustomers, None, "graphql.json"), + (MetafieldOrders, None, "graphql.json"), + (MetafieldDraftOrders, None, "graphql.json"), + (MetafieldProducts, None, "graphql.json"), + (MetafieldProductVariants, None, "graphql.json"), + (MetafieldLocations, None, "graphql.json"), + (MetafieldCollections, None, "graphql.json"), + # (MetafieldSmartCollections, {"id": 123}, "smart_collections/123/metafields.json"), - (MetafieldCollections, {"collection_id": 123}, "collections/123/metafields.json"), (MetafieldPages, {"id": 123}, "pages/123/metafields.json"), - (MetafieldLocations, {"id": 123}, "locations/123/metafields.json"), (MetafieldShops, None, "metafields.json"), - (ProductImages, {"product_id": 123}, "products/123/images.json"), - (ProductVariants, {"product_id": 123}, "products/123/variants.json"), + # Nested Substreams + (ProductImages, None, ""), + (ProductVariants, None, ""), + # (Customers, None, "customers.json"), (Orders, None, "orders.json"), (DraftOrders, None, "draft_orders.json"), @@ -87,7 +92,7 @@ def config(basic_config): (CustomCollections, None, "custom_collections.json"), ], ) -def test_customers_path(stream, stream_slice, expected_path, config): +def test_path(stream, stream_slice, expected_path, config) -> None: stream = stream(config) if stream_slice: result = stream.path(stream_slice) @@ -99,39 +104,47 @@ def test_customers_path(stream, stream_slice, expected_path, config): @pytest.mark.parametrize( "stream,stream_slice,expected_path", [ - (OrderRefunds, {"order_id": 12345}, "orders/12345/refunds.json"), (OrderRisks, {"order_id": 12345}, "orders/12345/risks.json"), (Transactions, {"order_id": 12345}, "orders/12345/transactions.json"), - (DiscountCodes, {"price_rule_id": 12345}, "price_rules/12345/discount_codes.json"), - (InventoryLevels, {"location_id": 12345}, "locations/12345/inventory_levels.json"), - (FulfillmentOrders, {"order_id": 12345}, "orders/12345/fulfillment_orders.json"), - (Fulfillments, {"order_id": 12345}, "orders/12345/fulfillments.json"), + # Nested Substreams + (OrderRefunds, None, ""), + (Fulfillments, None, ""), + # GQL BULK stream + (DiscountCodes, None, "graphql.json"), + (FulfillmentOrders, None, "graphql.json"), + (InventoryLevels, None, "graphql.json"), ], ) -def test_customers_path_with_stream_slice_param(stream, stream_slice, expected_path, config): +def test_path_with_stream_slice_param(stream, stream_slice, expected_path, config) -> None: stream = stream(config) - assert stream.path(stream_slice) == expected_path + if stream_slice: + result = stream.path(stream_slice) + else: + result = stream.path() + assert result == expected_path -def test_check_connection(config, mocker): - mocker.patch("source_shopify.source.Shop.read_records", return_value=[{"id": 1}]) +def test_check_connection(config, mocker) -> None: + mocker.patch("source_shopify.streams.streams.Shop.read_records", return_value=[{"id": 1}]) source = SourceShopify() logger_mock = MagicMock() assert source.check_connection(logger_mock, config) == (True, None) -def test_read_records(config, mocker): +def test_read_records(config, mocker) -> None: records = [{"created_at": "2022-10-10T06:21:53-07:00", "orders": {"updated_at": "2022-10-10T06:21:53-07:00"}}] stream_slice = records[0] stream = OrderRefunds(config) - mocker.patch("source_shopify.source.IncrementalShopifyStream.read_records", return_value=records) - assert next(stream.read_records(stream_slice=stream_slice)) == records[0] + mocker.patch("source_shopify.streams.base_streams.IncrementalShopifyNestedStream.read_records", return_value=records) + assert stream.read_records(stream_slice=stream_slice)[0] == records[0] @pytest.mark.parametrize( "stream, expected", [ - (OrderRefunds, {"limit": 250}), + # Nested Substream + (OrderRefunds, {}), + # (Orders, {"limit": 250, "status": "any", "order": "updated_at asc", "updated_at_min": "2020-11-01"}), ( AbandonedCheckouts, @@ -139,7 +152,7 @@ def test_read_records(config, mocker): ), ], ) -def test_request_params(config, stream, expected): +def test_request_params(config, stream, expected) -> None: assert stream(config).request_params() == expected @@ -168,12 +181,12 @@ def test_request_params(config, stream, expected): "no values at all", ], ) -def test_get_updated_state(config, last_record, current_state, expected): +def test_get_updated_state(config, last_record, current_state, expected) -> None: stream = OrderRefunds(config) assert stream.get_updated_state(current_state, last_record) == expected -def test_parse_response_with_bad_json(config, response_with_bad_json): +def test_parse_response_with_bad_json(config, response_with_bad_json) -> None: stream = Customers(config) assert list(stream.parse_response(response_with_bad_json)) == [{}] @@ -186,8 +199,30 @@ def test_parse_response_with_bad_json(config, response_with_bad_json): ], ids=["old style", "oauth style"], ) -def test_get_shop_name(config, shop, expected): +def test_get_shop_name(config, shop, expected) -> None: source = SourceShopify() config["shop"] = shop actual = source.get_shop_name(config) assert actual == expected + +@pytest.mark.parametrize( + "config, expected_stream_class", + [ + ({"fetch_transactions_user_id": False}, TransactionsGraphql), + ({"fetch_transactions_user_id": True}, Transactions), + ({}, TransactionsGraphql), + ], + ids=["don't fetch user_id", "fetch user id", "unset config value shouldn't fetch user_id"], +) +def test_select_transactions_stream(config, expected_stream_class): + config["shop"] = "test-store" + config["credentials"] = { + "auth_method": "api_password", + "api_password": "shppa_123" + } + config["authenticator"] = ShopifyAuthenticator(config) + + source = SourceShopify() + actual = source.select_transactions_stream(config) + assert type(actual) == expected_stream_class + diff --git a/airbyte-integrations/connectors/source-shopify/unit_tests/unit_test.py b/airbyte-integrations/connectors/source-shopify/unit_tests/unit_test.py index 14da41e6c0b1..d9c9e1ea0723 100644 --- a/airbyte-integrations/connectors/source-shopify/unit_tests/unit_test.py +++ b/airbyte-integrations/connectors/source-shopify/unit_tests/unit_test.py @@ -3,9 +3,12 @@ # +from unittest.mock import patch + import pytest import requests -from source_shopify.source import BalanceTransactions, DiscountCodes, FulfillmentOrders, PriceRules, SourceShopify +from source_shopify.source import ConnectionCheckTest, SourceShopify +from source_shopify.streams.streams import BalanceTransactions, DiscountCodes, FulfillmentOrders, PriceRules def test_get_next_page_token(requests_mock, auth_config): @@ -30,28 +33,54 @@ def test_get_next_page_token(requests_mock, auth_config): assert test == expected_output_token -def test_privileges_validation(requests_mock, basic_config): +@pytest.mark.parametrize( + "fetch_transactions_user_id, expected", + [ + ( + True, + [ + "abandoned_checkouts", + "fulfillments", + "metafield_orders", + "metafield_shops", + "order_refunds", + "order_risks", + "orders", + "shop", + "tender_transactions", + "transactions", + "countries", + ], + ), + ( + False, + [ + "abandoned_checkouts", + "fulfillments", + "metafield_orders", + "metafield_shops", + "order_refunds", + "order_risks", + "orders", + "shop", + "tender_transactions", + "transactions", + "countries", + ], + ), + ], +) +def test_privileges_validation(requests_mock, fetch_transactions_user_id, basic_config, expected): requests_mock.get( "https://test_shop.myshopify.com/admin/oauth/access_scopes.json", json={"access_scopes": [{"handle": "read_orders"}]}, ) - source = SourceShopify() - - expected = [ - "abandoned_checkouts", - "fulfillments", - "metafield_orders", - "metafield_shops", - "order_refunds", - "order_risks", - "orders", - "shop", - "tender_transactions", - "transactions", - "countries", - ] - - assert [stream.name for stream in source.streams(basic_config)] == expected + basic_config["fetch_transactions_user_id"] = fetch_transactions_user_id + # mock the get_shop_id method + with patch.object(ConnectionCheckTest, "get_shop_id", return_value=123) as mock: + source = SourceShopify() + streams = source.streams(basic_config) + assert [stream.name for stream in streams] == expected @pytest.mark.parametrize( diff --git a/docs/integrations/sources/shopify-migrations.md b/docs/integrations/sources/shopify-migrations.md index e811d2f5743e..0ecf880c31ae 100644 --- a/docs/integrations/sources/shopify-migrations.md +++ b/docs/integrations/sources/shopify-migrations.md @@ -1,5 +1,43 @@ # Shopify Migration Guide +## Upgrading to 2.0.0 +This version implements `Shopify GraphQL BULK Operations` to speed up the following streams: + - `Collections` + - `Customer Address` + - `Discount Codes` + - `Fulfillment Orders` + - `Inventory Items` + - `Inventory Levels` + - `Metafield Collections` + - `Metafield Customers` + - `Metafield Draft_orders` + - `Metafield Locations` + - `Metafield Orders` + - `Metafield Product Images` + - `Metafield Product Variants` + - `Transactions Graphql` (duplicated `Transactions` stream to provide faster fetch) + +Increased the performance for the following streams: +- `Fulfillments` +- `Order Refunds` +- `Product Images` +- `Product Variants` + +Other bug fixes and improvements, more info: `https://github.com/airbytehq/airbyte/pull/32345` + +### Action items required for 2.0.0 +* The `Fulfillments` stream now has the cursor field `updated_at`, instead of the `id`. +* The `Order Refunds` stream, now has the schema `refund_line_items.line_item.properties` to array of `strings`, instead of `object` with properties. +* The `Fulfillment Orders` stream now has the `supported_actions` schema as `array of objects` instead of `array of strings`. +* The `Collections` stream now requires additional api scope `read_publications` to fetch the `published_at` field with `GraphQL BULK Operations`. + + - if `API_PASSWORD` is used for authentication: + - BEFORE UPDATING to the `2.0.0`: update your `Private Developer Application` scopes with `read_publications` and save the changes, in your Shopify Account. + - if `OAuth2.0` is used for authentication: + - `re-auth` in order to obtain new scope automatically, after the upgrade. + - `Refresh Schema` + `Reset` is required for these streams after the upgrade from previous version. + + ## Upgrading to 1.0.0 This version uses Shopify API version `2023-07` which brings changes to the following streams: - removed `gateway, payment_details, processing_method` properties from `Order` stream, they are no longer supplied. diff --git a/docs/integrations/sources/shopify.md b/docs/integrations/sources/shopify.md index 5a5aa4b43b91..86b9ebdc35c3 100644 --- a/docs/integrations/sources/shopify.md +++ b/docs/integrations/sources/shopify.md @@ -85,6 +85,7 @@ Add the following scopes to your custom app to ensure Airbyte can sync all avail * `read_price_rules` * `read_product_listings` * `read_products` +* `read_publications` * `read_reports` * `read_resource_feedbacks` * `read_script_tags` @@ -105,43 +106,44 @@ Add the following scopes to your custom app to ensure Airbyte can sync all avail The Shopify source supports both Full Refresh and Incremental syncs. You can choose if this connector will copy only the new or updated data, or all rows in the tables and columns you set up for replication, every time a sync is run. -This source can sync data for the [Shopify REST API](https://shopify.dev/api/admin-rest) and the [Shopify GraphQl API](https://shopify.dev/api/admin-graphql). +This source can sync data for the [Shopify REST API](https://shopify.dev/api/admin-rest) and the [Shopify GraphQL API](https://shopify.dev/api/admin-graphql) and the [Shopify GraphQL BULK API](https://shopify.dev/docs/api/usage/bulk-operations/queries) ## Supported streams -- [Abandoned Checkouts](https://shopify.dev/api/admin-rest/2022-01/resources/abandoned-checkouts#top) -- [Articles](https://shopify.dev/api/admin-rest/2022-01/resources/article) +- [Abandoned Checkouts](https://shopify.dev/api/admin-rest/2023-07/resources/abandoned-checkouts#top) +- [Articles](https://shopify.dev/api/admin-rest/2023-07/resources/article) - [Balance Transactions](https://shopify.dev/docs/api/admin-rest/2023-10/resources/transactions) -- [Blogs](https://shopify.dev/api/admin-rest/2022-01/resources/blog) -- [Collects](https://shopify.dev/api/admin-rest/2022-01/resources/collect#top) -- [Collections](https://shopify.dev/api/admin-rest/2022-01/resources/collection) -- [Countries](https://shopify.dev/docs/api/admin-rest/2023-04/resources/country) -- [Custom Collections](https://shopify.dev/api/admin-rest/2022-01/resources/customcollection#top) -- [Customers](https://shopify.dev/api/admin-rest/2022-01/resources/customer#top) -- [Customer Address](https://shopify.dev/docs/api/admin-rest/2023-04/resources/customer-address) -- [Customer Saved Search](https://shopify.dev/docs/api/admin-rest/2023-04/resources/customersavedsearch) -- [Draft Orders](https://shopify.dev/api/admin-rest/2022-01/resources/draftorder#top) -- [Discount Codes](https://shopify.dev/api/admin-rest/2022-01/resources/discountcode#top) +- [Blogs](https://shopify.dev/api/admin-rest/2023-07/resources/blog) +- [Collects](https://shopify.dev/api/admin-rest/2023-07/resources/collect#top) +- [Collections (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/Collection) +- [Countries](https://shopify.dev/docs/api/admin-rest/2023-07/resources/country) +- [Custom Collections](https://shopify.dev/api/admin-rest/2023-07/resources/customcollection#top) +- [Customers](https://shopify.dev/api/admin-rest/2023-07/resources/customer#top) +- [Customer Address](https://shopify.dev/docs/api/admin-rest/2023-07/resources/customer-address) +- [Customer Saved Search](https://shopify.dev/docs/api/admin-rest/2023-07/resources/customersavedsearch) +- [Draft Orders](https://shopify.dev/api/admin-rest/2023-07/resources/draftorder#top) +- [Discount Codes (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/unions/DiscountCode) - [Disputes](https://shopify.dev/docs/api/admin-rest/2023-07/resources/dispute) -- [Fulfillments](https://shopify.dev/api/admin-rest/2022-01/resources/fulfillment) -- [Fulfillment Orders](https://shopify.dev/api/admin-rest/2022-01/resources/fulfillmentorder) -- [Inventory Items](https://shopify.dev/api/admin-rest/2022-01/resources/inventoryItem) -- [Inventory Levels](https://shopify.dev/api/admin-rest/2021-01/resources/inventorylevel) -- [Locations](https://shopify.dev/api/admin-rest/2022-01/resources/location) -- [Metafields](https://shopify.dev/api/admin-rest/2022-01/resources/metafield#top) -- [Orders](https://shopify.dev/api/admin-rest/2022-01/resources/order#top) -- [Order Refunds](https://shopify.dev/api/admin-rest/2022-01/resources/refund#top) -- [Order Risks](https://shopify.dev/api/admin-rest/2022-01/resources/order-risk#top) -- [Pages](https://shopify.dev/api/admin-rest/2022-01/resources/page#top) -- [Price Rules](https://shopify.dev/api/admin-rest/2022-01/resources/pricerule#top) -- [Products](https://shopify.dev/api/admin-rest/2022-01/resources/product#top) +- [Fulfillments](https://shopify.dev/api/admin-rest/2023-07/resources/fulfillment) +- [Fulfillment Orders (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/FulfillmentOrder) +- [Inventory Items (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/InventoryItem) +- [Inventory Levels (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/InventoryLevel) +- [Locations](https://shopify.dev/api/admin-rest/2023-07/resources/location) +- [Metafields (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/Metafield) +- [Orders](https://shopify.dev/api/admin-rest/2023-07/resources/order#top) +- [Order Refunds](https://shopify.dev/api/admin-rest/2023-07/resources/refund#top) +- [Order Risks](https://shopify.dev/api/admin-rest/2023-07/resources/order-risk#top) +- [Pages](https://shopify.dev/api/admin-rest/2023-07/resources/page#top) +- [Price Rules](https://shopify.dev/api/admin-rest/2023-07/resources/pricerule#top) +- [Products](https://shopify.dev/api/admin-rest/2023-07/resources/product#top) - [Products (GraphQL)](https://shopify.dev/api/admin-graphql/2022-10/queries/products) -- [Product Images](https://shopify.dev/api/admin-rest/2022-01/resources/product-image) -- [Product Variants](https://shopify.dev/api/admin-rest/2022-01/resources/product-variant) -- [Shop](https://shopify.dev/api/admin-rest/2022-01/resources/shop) -- [Smart Collections](https://shopify.dev/api/admin-rest/2022-01/resources/smartcollection) -- [Transactions](https://shopify.dev/api/admin-rest/2022-01/resources/transaction#top) -- [Tender Transactions](https://shopify.dev/api/admin-rest/2022-01/resources/tendertransaction) +- [Product Images](https://shopify.dev/api/admin-rest/2023-07/resources/product-image) +- [Product Variants](https://shopify.dev/api/admin-rest/2023-07/resources/product-variant) +- [Shop](https://shopify.dev/api/admin-rest/2023-07/resources/shop) +- [Smart Collections](https://shopify.dev/api/admin-rest/2023-07/resources/smartcollection) +- [Transactions](https://shopify.dev/api/admin-rest/2023-07/resources/transaction#top) +- [Transactions (GraphQL)](https://shopify.dev/docs/api/admin-graphql/2023-07/objects/OrderTransaction) +- [Tender Transactions](https://shopify.dev/api/admin-rest/2023-07/resources/tendertransaction) ## Capturing deleted records @@ -191,14 +193,8 @@ Waiting seconds then retrying..." This is expected when the connector hits a `429 - Rate Limit Exceeded` HTTP Error. The sync operation will continue successfully after a short backoff period. -#### Incremental sync recommendations +For all `Shopify GraphQL BULK` api requests these limitations are applied: https://shopify.dev/docs/api/usage/bulk-operations/queries#operation-restrictions -For the smoothest experience with Incremental Refresh sync mode, the following is recommended: - -- The `Order Refunds`, `Order Risks`, `Transactions` should be synced along with `Orders` stream. -- `Discount Codes` should be synced along with `Price Rules` stream. - -If a child stream is synced independently of its parent stream, a full sync will occur, followed by a filtering out of records. This process may be less efficient compared to syncing child streams alongside their respective parent streams. ### Troubleshooting @@ -211,6 +207,7 @@ If a child stream is synced independently of its parent stream, a full sync will | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| 2.0.0 | 2024-02-12 | [32345](https://github.com/airbytehq/airbyte/pull/32345) | Fixed the issue with `state` causing the `substreams` to skip the records, made `metafield_*`: `collections, customers, draft_orders, locations, orders, product_images, product_variants, products`, and `fulfillment_orders, collections, discount_codes, inventory_levels, inventory_items, transactions_graphql, customer_address` streams to use `BULK Operations` instead of `REST`| | 1.1.8 | 2024-02-12 | [35166](https://github.com/airbytehq/airbyte/pull/35166) | Manage dependencies with Poetry. | | 1.1.7 | 2024-01-19 | [33804](https://github.com/airbytehq/airbyte/pull/33804) | Updated documentation with list of all supported streams | | 1.1.6 | 2024-01-04 | [33414](https://github.com/airbytehq/airbyte/pull/33414) | Prepare for airbyte-lib |