├── .lycheeignore
├── .azdo
└── pipelines
│ └── azure-dev.yml
├── .devcontainer
├── azd-bicep
│ └── devcontainer.json
├── azd-terraform
│ └── devcontainer.json
├── btpsa
│ └── devcontainer.json
└── devcontainer.json
├── .gitattributes
├── .github
├── CODE_OF_CONDUCT.md
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ └── feature_request.yml
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── workflows
│ ├── azure-dev.yml
│ ├── codeql.yml
│ └── links-watcher.yml
├── .gitignore
├── .vscode
├── launch.json
└── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── assets
├── apim-backoff-delay.png
├── app-auth-principal-propagation.svg
├── azd-app-auth-flow.svg
├── bupa-create-vsc-rest.png
├── bupa-delete-vsc-rest.png
├── bupa-get-vsc-rest.png
├── bupa-update-vsc-rest.png
├── drawings.pptx
├── project-overview-azd-style.png
└── sap-cloud-sdk-auth.drawio
├── azure.yaml
├── documentation
├── ADDITIONAL-RESOURCES.md
├── AUTHENTICATION.md
├── AZD-CICD-SETUP.md
├── DEPLOYMENT-AZD-TERRAFORM.md
├── DEPLOYMENT-AZD.md
├── DEPLOYMENT-BTPSA.md
├── DEPLOYMENT-VSCODE.md
└── WHATS-NEXT.md
├── hooks
├── createAppRegistrations.ps1
├── deleteAppRegistrations.ps1
└── fireworks.sh
├── infra-btpsa
├── parameters.json
└── usecase.json
├── infra-terraform
├── main.tf
├── main.tfvars.json
├── modules
│ ├── apim-api
│ │ ├── apim-api-policy.xml
│ │ ├── apim-api.tf
│ │ ├── apim-api_output.tf
│ │ └── apim-api_variables.tf
│ ├── apim
│ │ ├── apim.tf
│ │ ├── apim_output.tf
│ │ └── apim_variables.tf
│ ├── applicationinsights
│ │ ├── applicationinsights.tf
│ │ ├── applicationinsights_output.tf
│ │ └── applicationinsights_variables.tf
│ ├── appservicenode
│ │ ├── appservicenode.tf
│ │ ├── appservicenode_output.tf
│ │ └── appservicenode_variables.tf
│ ├── appserviceplan
│ │ ├── appserviceplan.tf
│ │ ├── appserviceplan_output.tf
│ │ └── appserviceplan_variables.tf
│ ├── cosmos
│ │ ├── cosmos.tf
│ │ ├── cosmos_output.tf
│ │ └── cosmos_variables.tf
│ ├── keyvault
│ │ ├── keyvault.tf
│ │ ├── keyvault_output.tf
│ │ └── keyvault_variables.tf
│ └── loganalytics
│ │ ├── loganalytics.tf
│ │ ├── loganalytics_output.tf
│ │ └── loganalytics_variables.tf
├── modules_local
│ ├── apim-api
│ │ ├── apim-api-policy.xml
│ │ ├── apim-api.tf
│ │ ├── apim-api_output.tf
│ │ └── apim-api_variables.tf
│ └── appservicenode
│ │ ├── appservicenode.tf
│ │ ├── appservicenode_output.tf
│ │ └── appservicenode_variables.tf
├── output.tf
├── provider.tf
└── variables.tf
├── infra
├── abbreviations.json
├── app
│ ├── api.bicep
│ ├── apim-api-policy.xml
│ └── apim-api.bicep
├── core
│ ├── ai
│ │ └── cognitiveservices.bicep
│ ├── config
│ │ └── configstore.bicep
│ ├── database
│ │ ├── cosmos
│ │ │ ├── cosmos-account.bicep
│ │ │ ├── mongo
│ │ │ │ ├── cosmos-mongo-account.bicep
│ │ │ │ └── cosmos-mongo-db.bicep
│ │ │ └── sql
│ │ │ │ ├── cosmos-sql-account.bicep
│ │ │ │ ├── cosmos-sql-db.bicep
│ │ │ │ ├── cosmos-sql-role-assign.bicep
│ │ │ │ └── cosmos-sql-role-def.bicep
│ │ ├── mysql
│ │ │ └── flexibleserver.bicep
│ │ ├── postgresql
│ │ │ └── flexibleserver.bicep
│ │ └── sqlserver
│ │ │ └── sqlserver.bicep
│ ├── gateway
│ │ └── apim.bicep
│ ├── host
│ │ ├── aks-agent-pool.bicep
│ │ ├── aks-managed-cluster.bicep
│ │ ├── aks.bicep
│ │ ├── appservice-appsettings.bicep
│ │ ├── appservice.bicep
│ │ ├── appserviceplan.bicep
│ │ ├── container-app-upsert.bicep
│ │ ├── container-app.bicep
│ │ ├── container-apps-environment.bicep
│ │ ├── container-apps.bicep
│ │ ├── container-registry.bicep
│ │ ├── functions.bicep
│ │ └── staticwebapp.bicep
│ ├── monitor
│ │ ├── applicationinsights-dashboard.bicep
│ │ ├── applicationinsights.bicep
│ │ ├── loganalytics.bicep
│ │ └── monitoring.bicep
│ ├── networking
│ │ ├── cdn-endpoint.bicep
│ │ ├── cdn-profile.bicep
│ │ └── cdn.bicep
│ ├── search
│ │ └── search-services.bicep
│ ├── security
│ │ ├── aks-managed-cluster-access.bicep
│ │ ├── configstore-access.bicep
│ │ ├── keyvault-access.bicep
│ │ ├── keyvault-secret.bicep
│ │ ├── keyvault.bicep
│ │ ├── registry-access.bicep
│ │ └── role.bicep
│ ├── storage
│ │ └── storage-account.bicep
│ └── testing
│ │ └── loadtesting.bicep
├── core_local
│ └── host
│ │ └── appservice.bicep
├── main.bicep
└── main.parameters.json
├── package-lock.json
├── package.json
├── sample-http-requests
├── SAP-Cloud-SDK-on-Azure-App-Service-Quickstart.postman_collection.json
└── business-partner-requests.http
├── src
└── api
│ ├── .deployment
│ ├── .gitignore
│ ├── API_BUSINESS_PARTNER.edmx
│ ├── API_BUSINESS_PARTNER.openapi.json
│ ├── manifest.yaml
│ ├── nest-cli.json
│ ├── package-lock.json
│ ├── package.json
│ ├── rome.json
│ ├── service-specifications
│ ├── ZAPI_BUSINESS_PARTNER.edmx
│ └── config.json
│ ├── services
│ └── business-partner-service-1
│ │ ├── AddressEmailAddress.ts
│ │ ├── AddressEmailAddressApi.ts
│ │ ├── AddressEmailAddressRequestBuilder.ts
│ │ ├── AddressFaxNumber.ts
│ │ ├── AddressFaxNumberApi.ts
│ │ ├── AddressFaxNumberRequestBuilder.ts
│ │ ├── AddressHomePageUrl.ts
│ │ ├── AddressHomePageUrlApi.ts
│ │ ├── AddressHomePageUrlRequestBuilder.ts
│ │ ├── AddressPhoneNumber.ts
│ │ ├── AddressPhoneNumberApi.ts
│ │ ├── AddressPhoneNumberRequestBuilder.ts
│ │ ├── BatchRequest.ts
│ │ ├── BpContactToAddress.ts
│ │ ├── BpContactToAddressApi.ts
│ │ ├── BpContactToAddressRequestBuilder.ts
│ │ ├── BpContactToFuncAndDept.ts
│ │ ├── BpContactToFuncAndDeptApi.ts
│ │ ├── BpContactToFuncAndDeptRequestBuilder.ts
│ │ ├── BuPaAddressUsage.ts
│ │ ├── BuPaAddressUsageApi.ts
│ │ ├── BuPaAddressUsageRequestBuilder.ts
│ │ ├── BuPaIdentification.ts
│ │ ├── BuPaIdentificationApi.ts
│ │ ├── BuPaIdentificationRequestBuilder.ts
│ │ ├── BuPaIndustry.ts
│ │ ├── BuPaIndustryApi.ts
│ │ ├── BuPaIndustryRequestBuilder.ts
│ │ ├── BusinessPartner.ts
│ │ ├── BusinessPartnerAddress.ts
│ │ ├── BusinessPartnerAddressApi.ts
│ │ ├── BusinessPartnerAddressRequestBuilder.ts
│ │ ├── BusinessPartnerApi.ts
│ │ ├── BusinessPartnerBank.ts
│ │ ├── BusinessPartnerBankApi.ts
│ │ ├── BusinessPartnerBankRequestBuilder.ts
│ │ ├── BusinessPartnerContact.ts
│ │ ├── BusinessPartnerContactApi.ts
│ │ ├── BusinessPartnerContactRequestBuilder.ts
│ │ ├── BusinessPartnerRequestBuilder.ts
│ │ ├── BusinessPartnerRole.ts
│ │ ├── BusinessPartnerRoleApi.ts
│ │ ├── BusinessPartnerRoleRequestBuilder.ts
│ │ ├── BusinessPartnerTaxNumber.ts
│ │ ├── BusinessPartnerTaxNumberApi.ts
│ │ ├── BusinessPartnerTaxNumberRequestBuilder.ts
│ │ ├── CustSalesPartnerFunc.ts
│ │ ├── CustSalesPartnerFuncApi.ts
│ │ ├── CustSalesPartnerFuncRequestBuilder.ts
│ │ ├── Customer.ts
│ │ ├── CustomerApi.ts
│ │ ├── CustomerCompany.ts
│ │ ├── CustomerCompanyApi.ts
│ │ ├── CustomerCompanyRequestBuilder.ts
│ │ ├── CustomerCompanyText.ts
│ │ ├── CustomerCompanyTextApi.ts
│ │ ├── CustomerCompanyTextRequestBuilder.ts
│ │ ├── CustomerDunning.ts
│ │ ├── CustomerDunningApi.ts
│ │ ├── CustomerDunningRequestBuilder.ts
│ │ ├── CustomerRequestBuilder.ts
│ │ ├── CustomerSalesArea.ts
│ │ ├── CustomerSalesAreaApi.ts
│ │ ├── CustomerSalesAreaRequestBuilder.ts
│ │ ├── CustomerSalesAreaTax.ts
│ │ ├── CustomerSalesAreaTaxApi.ts
│ │ ├── CustomerSalesAreaTaxRequestBuilder.ts
│ │ ├── CustomerSalesAreaText.ts
│ │ ├── CustomerSalesAreaTextApi.ts
│ │ ├── CustomerSalesAreaTextRequestBuilder.ts
│ │ ├── CustomerTaxGrouping.ts
│ │ ├── CustomerTaxGroupingApi.ts
│ │ ├── CustomerTaxGroupingRequestBuilder.ts
│ │ ├── CustomerText.ts
│ │ ├── CustomerTextApi.ts
│ │ ├── CustomerTextRequestBuilder.ts
│ │ ├── CustomerUnloadingPoint.ts
│ │ ├── CustomerUnloadingPointApi.ts
│ │ ├── CustomerUnloadingPointRequestBuilder.ts
│ │ ├── CustomerWithHoldingTax.ts
│ │ ├── CustomerWithHoldingTaxApi.ts
│ │ ├── CustomerWithHoldingTaxRequestBuilder.ts
│ │ ├── Supplier.ts
│ │ ├── SupplierApi.ts
│ │ ├── SupplierCompany.ts
│ │ ├── SupplierCompanyApi.ts
│ │ ├── SupplierCompanyRequestBuilder.ts
│ │ ├── SupplierCompanyText.ts
│ │ ├── SupplierCompanyTextApi.ts
│ │ ├── SupplierCompanyTextRequestBuilder.ts
│ │ ├── SupplierDunning.ts
│ │ ├── SupplierDunningApi.ts
│ │ ├── SupplierDunningRequestBuilder.ts
│ │ ├── SupplierPartnerFunc.ts
│ │ ├── SupplierPartnerFuncApi.ts
│ │ ├── SupplierPartnerFuncRequestBuilder.ts
│ │ ├── SupplierPurchasingOrg.ts
│ │ ├── SupplierPurchasingOrgApi.ts
│ │ ├── SupplierPurchasingOrgRequestBuilder.ts
│ │ ├── SupplierPurchasingOrgText.ts
│ │ ├── SupplierPurchasingOrgTextApi.ts
│ │ ├── SupplierPurchasingOrgTextRequestBuilder.ts
│ │ ├── SupplierRequestBuilder.ts
│ │ ├── SupplierText.ts
│ │ ├── SupplierTextApi.ts
│ │ ├── SupplierTextRequestBuilder.ts
│ │ ├── SupplierWithHoldingTax.ts
│ │ ├── SupplierWithHoldingTaxApi.ts
│ │ ├── SupplierWithHoldingTaxRequestBuilder.ts
│ │ ├── index.ts
│ │ └── service.ts
│ ├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── business-partner
│ │ ├── business-partner.controller.spec.ts
│ │ ├── business-partner.controller.ts
│ │ ├── business-partner.service.spec.ts
│ │ └── business-partner.service.ts
│ ├── main.ts
│ ├── public
│ │ ├── github-logo.svg
│ │ ├── sap-cloud-sdk-logo.svg
│ │ └── stylesheets
│ │ │ └── style.css
│ └── views
│ │ ├── bupa.pug
│ │ └── index.pug
│ ├── tsconfig.build.json
│ └── tsconfig.json
├── templates
├── .env
├── azuredeploy.json
└── azuredeploy.parameters.json
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
└── workspaces
├── azd-bicep.code-workspace
├── azd-terraform.code-workspace
└── btpsa.code-workspace
/ .lycheeignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/ .lycheeignore
--------------------------------------------------------------------------------
/.azdo/pipelines/azure-dev.yml:
--------------------------------------------------------------------------------
1 | trigger:
2 | - main
3 |
4 | pool:
5 | vmImage: ubuntu-latest
6 |
7 | steps:
8 | - task: setup-azd@0
9 | displayName: Install azd
10 |
11 | - pwsh: |
12 | $info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
13 |
14 | azd auth login `
15 | --client-id "$($info.clientId)" `
16 | --client-secret "$($info.clientSecret)" `
17 | --tenant-id "$($info.tenantId)"
18 | displayName: azd login
19 | env:
20 | AZURE_CREDENTIALS: $(AZURE_CREDENTIALS)
21 |
22 | - task: AzureCLI@2
23 | displayName: Azure Dev Provision
24 | inputs:
25 | azureSubscription: azconnection
26 | scriptType: bash
27 | scriptLocation: inlineScript
28 | inlineScript: |
29 | azd provision --no-prompt
30 | env:
31 | AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
32 | AZURE_ENV_NAME: $(AZURE_ENV_NAME)
33 | AZURE_LOCATION: $(AZURE_LOCATION)
34 | ARM_TENANT_ID: $(ARM_TENANT_ID)
35 | ARM_CLIENT_ID: $(ARM_CLIENT_ID)
36 | ARM_CLIENT_SECRET: $(ARM_CLIENT_SECRET)
37 | RS_RESOURCE_GROUP: $(RS_RESOURCE_GROUP)
38 | RS_STORAGE_ACCOUNT: $(RS_STORAGE_ACCOUNT)
39 | RS_CONTAINER_NAME: $(RS_CONTAINER_NAME)
40 | ODATA_URL: $(ODATA_URL)
41 | ODATA_USERNAME: $(ODATA_USERNAME)
42 | ODATA_USERPWD: $(ODATA_USERPWD)
43 | APIKEY: $(APIKEY)
44 | APIKEY_HEADERNAME: $(APIKEY_HEADERNAME)
45 |
46 | - task: AzureCLI@2
47 | displayName: Azure Dev Deploy
48 | inputs:
49 | azureSubscription: azconnection
50 | scriptType: bash
51 | scriptLocation: inlineScript
52 | inlineScript: |
53 | azd deploy --no-prompt
54 | env:
55 | AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
56 | AZURE_ENV_NAME: $(AZURE_ENV_NAME)
57 | AZURE_LOCATION: $(AZURE_LOCATION)
58 | ODATA_URL: $(ODATA_URL)
59 | ODATA_USERNAME: $(ODATA_USERNAME)
60 | ODATA_USERPWD: $(ODATA_USERPWD)
61 | APIKEY: $(APIKEY)
62 | APIKEY_HEADERNAME: $(APIKEY_HEADERNAME)
63 |
--------------------------------------------------------------------------------
/.devcontainer/azd-bicep/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json.
2 | {
3 | "name": "Azure Developer CLI (Bicep)",
4 | "image": "mcr.microsoft.com/devcontainers/typescript-node:20-bullseye",
5 | "features": {
6 | "ghcr.io/devcontainers-contrib/features/nestjs-cli:2": {},
7 | "ghcr.io/devcontainers/features/docker-in-docker:2": {},
8 | "ghcr.io/devcontainers/features/azure-cli:1": {},
9 | "ghcr.io/azure/azure-dev/azd:latest": {},
10 | "ghcr.io/devcontainers/features/github-cli:1": {
11 | "version": "2"
12 | },
13 | "ghcr.io/devcontainers/features/powershell:1": {}
14 | },
15 | "customizations": {
16 | "vscode": {
17 | "extensions": [
18 | "GitHub.vscode-github-actions",
19 | "ms-azuretools.azure-dev",
20 | "ms-azuretools.vscode-azurefunctions",
21 | "ms-azuretools.vscode-bicep",
22 | "ms-azuretools.vscode-docker",
23 | "ms-vscode.js-debug",
24 | "ms-vscode.vscode-node-azure-pack",
25 | "humao.rest-client",
26 | "rome.rome"
27 | ]
28 | }
29 | },
30 | "forwardPorts": [
31 | 8080
32 | ],
33 | "postCreateCommand": "cd src/api && npm install && cd ../.. && chmod -R a+x /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/hooks",
34 | "remoteUser": "node",
35 | "hostRequirements": {
36 | "memory": "8gb"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.devcontainer/azd-terraform/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json.
2 | {
3 | "name": "Azure Developer CLI (Terraform)",
4 | "image": "mcr.microsoft.com/devcontainers/typescript-node:20-bullseye",
5 | "features": {
6 | "ghcr.io/devcontainers-contrib/features/nestjs-cli:2": {},
7 | "ghcr.io/devcontainers/features/azure-cli:1": {},
8 | "ghcr.io/devcontainers/features/docker-in-docker:2": {},
9 | "ghcr.io/azure/azure-dev/azd:latest": {},
10 | "ghcr.io/devcontainers/features/terraform:1": {
11 | "version": "latest"
12 | },
13 | "ghcr.io/devcontainers/features/powershell:1": {}
14 | },
15 | "customizations": {
16 | "vscode": {
17 | "extensions": [
18 | "GitHub.vscode-github-actions",
19 | "ms-azuretools.azure-dev",
20 | "ms-azuretools.vscode-azurefunctions",
21 | "ms-azuretools.vscode-bicep",
22 | "ms-azuretools.vscode-docker",
23 | "ms-vscode.js-debug",
24 | "ms-vscode.vscode-node-azure-pack",
25 | "humao.rest-client",
26 | "rome.rome"
27 | ]
28 | }
29 | },
30 | "forwardPorts": [
31 | 8080
32 | ],
33 | "postCreateCommand": "cd src/api && npm install && cd ../.. && azd config set auth.useAzCliAuth true",
34 | "remoteUser": "node",
35 | "hostRequirements": {
36 | "memory": "8gb"
37 | }
38 | }
--------------------------------------------------------------------------------
/.devcontainer/btpsa/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BTP Setup Automator (Stable)",
3 | "image": "ghcr.io/sap-samples/btp-setup-automator:latest",
4 | "customizations": {
5 | "vscode": {
6 | "settings": {
7 | "python.defaultInterpreterPath": "/usr/local/bin/python3",
8 | "python.linting.enabled": true,
9 | "python.formatting.provider": "black",
10 | "python.linting.flake8Enabled": true,
11 | "python.linting.flake8Args": [
12 | "--ignore=E501,F405,W504"
13 | ],
14 | "python.linting.pylintEnabled": false
15 | },
16 | "extensions": [
17 | "ms-python.python",
18 | "ms-python.vscode-pylance"
19 | ]
20 | },
21 | "codespaces": {
22 | "openFiles": [
23 | "parameters.json",
24 | "usecase.json"
25 | ]
26 | }
27 | },
28 | "remoteUser": "user",
29 | "postCreateCommand": "cp -f /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/infra-btpsa/parameters.json /home/user/parameters.json && cp -f /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/infra-btpsa/usecase.json /home/user/usecase.json && cd /home/user && echo 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.profile && pip install flake8 black && source ~/.profile",
30 | "workspaceFolder": "/home/user",
31 | "hostRequirements": {
32 | "cpus": 2,
33 | "memory": "4gb",
34 | "storage": "32gb"
35 | }
36 | }
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json.
2 | {
3 | "name": "Azure Developer CLI (Default - Bicep)",
4 | "image": "mcr.microsoft.com/devcontainers/typescript-node:20-bullseye",
5 | "features": {
6 | "ghcr.io/devcontainers-contrib/features/nestjs-cli:2": {},
7 | "ghcr.io/devcontainers/features/docker-in-docker:2": {},
8 | "ghcr.io/devcontainers/features/azure-cli:1": {},
9 | "ghcr.io/azure/azure-dev/azd:latest": {},
10 | "ghcr.io/devcontainers/features/github-cli:1": {
11 | "version": "2"
12 | },
13 | "ghcr.io/devcontainers/features/powershell:1": {}
14 | },
15 | "customizations": {
16 | "vscode": {
17 | "extensions": [
18 | "GitHub.vscode-github-actions",
19 | "ms-azuretools.azure-dev",
20 | "ms-azuretools.vscode-azurefunctions",
21 | "ms-azuretools.vscode-bicep",
22 | "ms-azuretools.vscode-docker",
23 | "ms-vscode.js-debug",
24 | "ms-vscode.vscode-node-azure-pack",
25 | "humao.rest-client",
26 | "rome.rome"
27 | ]
28 | }
29 | },
30 | "forwardPorts": [
31 | 8080
32 | ],
33 | "postCreateCommand": "cd src/api && npm install && cd ../.. && chmod -R a+x /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/hooks",
34 | "remoteUser": "node",
35 | "hostRequirements": {
36 | "memory": "8gb"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | *.{cmd,[cC][mM][dD]} text eol=crlf
3 | *.{bat,[bB][aA][tT]} text eol=crlf
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐞 Bug report
2 | description: File a bug/issue to help us improve
3 | title: "[BUG]"
4 | labels: [bug]
5 | assignees: [MartinPankraz]
6 | body:
7 | - type: checkboxes
8 | attributes:
9 | label: Is there an existing issue for this?
10 | description: Please search to see if an issue already exists for the bug you encountered.
11 | options:
12 | - label: I have searched the existing issues
13 | required: true
14 | - type: dropdown
15 | id: area
16 | attributes:
17 | label: What type of issue are you facing
18 | description: What type of issue are you facing?
19 | options:
20 | - bug report
21 | - documentation issue or request
22 | - regression (a behavior that used to work and stopped in a new version)
23 | validations:
24 | required: true
25 | - type: textarea
26 | attributes:
27 | label: Describe the bug
28 | description: Provide a clear and concise description of what the bug is.
29 | validations:
30 | required: true
31 | - type: textarea
32 | attributes:
33 | label: Expected Behavior
34 | description: A concise description of what you expected to happen.
35 | validations:
36 | required: false
37 | - type: textarea
38 | attributes:
39 | label: Steps To Reproduce
40 | description: Steps to reproduce the behavior.
41 | placeholder: |
42 | 1. Go to '...'
43 | 2. Click on '....'
44 | 3. Scroll down to '....'
45 | 4. See error
46 | validations:
47 | required: false
48 | - type: textarea
49 | attributes:
50 | label: Add screenshots to help explain your problem
51 | description: |
52 | If applicable, add screenshots to help explain your problem.
53 |
54 | Tip: You can attach images or files by clicking this area to highlight it and then dragging files in.
55 | validations:
56 | required: false
57 | - type: textarea
58 | attributes:
59 | label: Additional context
60 | description: |
61 | Add any other context like links or references about the problem here. Anything that will give us more context about the issue you are encountering!
62 |
63 | Tip: You can attach images or files by clicking this area to highlight it and then dragging files in.
64 | validations:
65 | required: false
66 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: 💡Feature request
2 | description: Suggest an idea for this project
3 | title: "[FEATURE]"
4 | labels: [enhancement]
5 | assignees: [MartinPankraz]
6 | body:
7 | - type: dropdown
8 | attributes:
9 | label: What area do you want to see improved?
10 | description: Specify the main area that you want to see improved.
11 | options:
12 | - app code
13 | - documentation
14 | - infrastructure setup
15 | - developer experience (GitHub CodeSpaces etc.)
16 | - other
17 | validations:
18 | required: true
19 | - type: textarea
20 | id: area
21 | attributes:
22 | label: Is your feature request related to a problem? Please describe.
23 | description: Provide a clear and concise description of what the problem is e.g., I'm always frustrated when [...]
24 | validations:
25 | required: true
26 | - type: textarea
27 | attributes:
28 | label: Describe the solution you'd like
29 | description: A clear and concise description of what you want to happen.
30 | validations:
31 | required: true
32 | - type: textarea
33 | attributes:
34 | label: Describe alternatives you've considered
35 | description: A clear and concise description of any alternative solutions or features you've considered.
36 | validations:
37 | required: false
38 | - type: textarea
39 | attributes:
40 | label: Additional context
41 | description: |
42 | Add any other context like links or references about the problem here. Anything that will give us more context about the issue you are encountering!
43 |
44 | Tip: You can attach images or files by clicking this area to highlight it and then dragging files in.
45 | validations:
46 | required: false
47 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Purpose
2 |
3 | * ...
4 |
5 | ## Does this introduce a breaking change?
6 |
7 | ```
8 | [ ] Yes
9 | [ ] No
10 | ```
11 |
12 | ## Pull Request Type
13 | What kind of change does this Pull Request introduce?
14 |
15 |
16 | ```
17 | [ ] Bugfix
18 | [ ] Feature
19 | [ ] Code style update (formatting, local variables)
20 | [ ] Refactoring (no functional changes, no api changes)
21 | [ ] Documentation content changes
22 | [ ] Other... Please describe:
23 | ```
24 |
25 | ## How to Test
26 | * Get the code
27 |
28 | ```
29 | git clone [repo-address]
30 | cd [repo-name]
31 | git checkout [branch-name]
32 | npm install
33 | ```
34 |
35 | * Test the code
36 |
37 | ```
38 | ```
39 |
40 | ## What to Check
41 | Verify that the following are valid
42 | * ...
43 |
44 | ## Other Information
45 |
46 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | # Check for updates to GitHub Actions once a week on Monday
7 | interval: "weekly"
8 | day: "monday"
9 | - package-ecosystem: "npm"
10 | directory: "/"
11 | schedule:
12 | interval: "weekly"
13 | day: "monday"
14 | - package-ecosystem: "devcontainers"
15 | directory: "/"
16 | schedule:
17 | interval: "weekly"
18 | day: "monday"
19 |
--------------------------------------------------------------------------------
/.github/workflows/azure-dev.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_dispatch:
3 |
4 | # Remove comment of this section once you want to use the setup via GH Actions
5 | # push:
6 | # branches:
7 | # - main
8 | # pull_request:
9 | # branches:
10 | # - main
11 |
12 | # https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v4
20 |
21 | - name: Install azd
22 | uses: Azure/setup-azd@v2.0.0
23 |
24 | - name: Install Nodejs
25 | uses: actions/setup-node@v4
26 | with:
27 | node-version: 18
28 |
29 | - name: Login az
30 | uses: azure/login@v2
31 | with:
32 | creds: ${{ secrets.AZURE_CREDENTIALS }}
33 |
34 | - name: Set az account
35 | uses: azure/CLI@v2
36 | with:
37 | inlineScript: |
38 | az account set --subscription ${{vars.AZURE_SUBSCRIPTION_ID}}
39 |
40 | - name: Log in with Azure
41 | run: |
42 | $info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
43 | Write-Host "::add-mask::$($info.clientSecret)"
44 |
45 | azd auth login `
46 | --client-id "$($info.clientId)" `
47 | --client-secret "$($info.clientSecret)" `
48 | --tenant-id "$($info.tenantId)"
49 | shell: pwsh
50 | env:
51 | AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
52 |
53 | - name: Azure Dev Provision
54 | run: azd provision --no-prompt
55 | env:
56 | AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
57 | AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
58 | AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
59 | ARM_TENANT_ID: ${{ vars.ARM_TENANT_ID }}
60 | ARM_CLIENT_ID: ${{ vars.ARM_CLIENT_ID }}
61 | ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
62 | RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }}
63 | RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }}
64 | RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }}
65 | ODATA_URL: ${{ secrets.ODATA_URL }}
66 | ODATA_USERNAME: ${{ secrets.ODATA_USERNAME }}
67 | ODATA_USERPWD: ${{ secrets.ODATA_USERPWD }}
68 | APIKEY: ${{ secrets.APIKEY }}
69 | APIKEY_HEADERNAME: ${{ secrets.APIKEY_HEADERNAME }}
70 |
71 | - name: Azure Dev Deploy
72 | run: azd deploy --no-prompt
73 | env:
74 | AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
75 | AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
76 | AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
77 | ODATA_URL: ${{ secrets.ODATA_URL }}
78 | ODATA_USERNAME: ${{ secrets.ODATA_USERNAME }}
79 | ODATA_USERPWD: ${{ secrets.ODATA_USERPWD }}
80 | APIKEY: ${{ secrets.APIKEY }}
81 | APIKEY_HEADERNAME: ${{ secrets.APIKEY_HEADERNAME }}
82 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "main" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "main" ]
20 | schedule:
21 | - cron: '37 7 * * 6'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Use only 'java' to analyze code written in Java, Kotlin or both
38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
40 |
41 | steps:
42 | - name: Checkout repository
43 | uses: actions/checkout@v4
44 |
45 | # Initializes the CodeQL tools for scanning.
46 | - name: Initialize CodeQL
47 | uses: github/codeql-action/init@v3
48 | with:
49 | languages: ${{ matrix.language }}
50 | # If you wish to specify custom queries, you can do so here or in a config file.
51 | # By default, queries listed here will override any specified in a config file.
52 | # Prefix the list here with "+" to use these queries and those in the config file.
53 |
54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55 | # queries: security-extended,security-and-quality
56 |
57 |
58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
59 | # If this step fails, then you should remove it and run the build manually (see below)
60 | - name: Autobuild
61 | uses: github/codeql-action/autobuild@v3
62 |
63 | # ℹ️ Command-line programs to run using the OS shell.
64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
65 |
66 | # If the Autobuild fails above, remove it and uncomment the following three lines.
67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
68 |
69 | # - run: |
70 | # echo "Run, Build Application using script"
71 | # ./location_of_script_within_repo/buildscript.sh
72 |
73 | - name: Perform CodeQL Analysis
74 | uses: github/codeql-action/analyze@v3
75 | with:
76 | category: "/language:${{matrix.language}}"
77 |
--------------------------------------------------------------------------------
/.github/workflows/links-watcher.yml:
--------------------------------------------------------------------------------
1 | name: Periodic Link Checker
2 |
3 | on:
4 | schedule:
5 | - cron: "0 23 * * *"
6 | workflow_dispatch:
7 |
8 | permissions:
9 | contents: read
10 | issues: write
11 |
12 | jobs:
13 | link-checker:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: "Checkout source code"
17 | uses: actions/checkout@v4
18 | - name: Link Checker
19 | id: lychee
20 | uses: lycheeverse/lychee-action@v2.2.0
21 | with:
22 | args: --verbose --no-progress --max-concurrency 2 --exclude-link-local --exclude-loopback './**/*.md' --exclude portal.azure.com --exclude developers.sap.com
23 | output: ./lychee/out.md
24 | fail: true
25 | env:
26 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
27 | - name: Find existing issue
28 | id: find_issue
29 | uses: micalevisk/last-issue-action@v2
30 | if: failure()
31 | with:
32 | state: open
33 | labels: |
34 | broken link
35 | automated issue
36 | - name: Create or update issue for broken links
37 | uses: peter-evans/create-issue-from-file@v5
38 | if: failure()
39 | with:
40 | title: Link Checker Report
41 | # If issue number is empty a new issue gets created
42 | issue-number: ${{ steps.find_issue.outputs.issue-number }}
43 | content-filepath: ./lychee/out.md
44 | labels: broken link, automated issue
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .azure
2 | node_modules
3 | dist
4 | infra-terraform/.terraform.lock.hcl
5 | .$*.bkp
6 | .$*.dtmp
7 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node-terminal",
9 | "name": "Run npm start:dev",
10 | "request": "launch",
11 | "command": "npm run start:dev",
12 | "cwd": "${workspaceFolder}/src/api"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "appService.zipIgnorePattern": [
3 | "node_modules{,/**}",
4 | ".vscode{,/**}",
5 | "img{,/**}",
6 | "templates{,/**}",
7 | ".env"
8 | ],
9 | "appService.deploySubpath": "src/api"
10 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [project-title] Changelog
2 |
3 |
4 | # x.y.z (yyyy-mm-dd)
5 |
6 | *Features*
7 | * ...
8 |
9 | *Bug Fixes*
10 | * ...
11 |
12 | *Breaking Changes*
13 | * ...
14 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
--------------------------------------------------------------------------------
/assets/apim-backoff-delay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/apim-backoff-delay.png
--------------------------------------------------------------------------------
/assets/bupa-create-vsc-rest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/bupa-create-vsc-rest.png
--------------------------------------------------------------------------------
/assets/bupa-delete-vsc-rest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/bupa-delete-vsc-rest.png
--------------------------------------------------------------------------------
/assets/bupa-get-vsc-rest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/bupa-get-vsc-rest.png
--------------------------------------------------------------------------------
/assets/bupa-update-vsc-rest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/bupa-update-vsc-rest.png
--------------------------------------------------------------------------------
/assets/drawings.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/drawings.pptx
--------------------------------------------------------------------------------
/assets/project-overview-azd-style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart/0675ad44767ad29593e6a6f62ee442bdd4169b57/assets/project-overview-azd-style.png
--------------------------------------------------------------------------------
/azure.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
2 |
3 | name: app-service-javascript-sap-cloud-sdk-quickstart
4 | metadata:
5 | template: app-service-javascript-sap-cloud-sdk-quickstart
6 | requiredVersions:
7 | azd: ">= 1.4.0"
8 | hooks:
9 | postup:
10 | posix:
11 | shell: sh
12 | run: ./hooks/fireworks.sh
13 | continueOnError: true
14 | interactive: true
15 | postprovision:
16 | posix:
17 | shell: pwsh
18 | run: ./hooks/createAppRegistrations.ps1
19 | continueOnError: false
20 | interactive: true
21 | windows:
22 | shell: pwsh
23 | run: ./hooks/createAppRegistrations.ps1
24 | continueOnError: false
25 | interactive: true
26 | #postdown:
27 | #posix:
28 | # shell: pwsh
29 | # run: ./hooks/deleteAppRegistrations.ps1
30 | # continueOnError: true
31 | # interactive: true
32 | #windows:
33 | # shell: pwsh
34 | # run: ./hooks/deleteAppRegistrations.ps1
35 | # continueOnError: false
36 | # interactive: true
37 | services:
38 | sap-cloud-sdk-api:
39 | project: ./src/api
40 | language: ts
41 | host: appservice
42 | # Remove the comments from the lines below to enable the deployment of the infrastructure via Terraform
43 | #infra:
44 | # provider: terraform
45 | # path: ./infra-terraform
46 |
--------------------------------------------------------------------------------
/documentation/ADDITIONAL-RESOURCES.md:
--------------------------------------------------------------------------------
1 | # Additional resources
2 |
3 | ## Details
4 |
5 | * [SAP Cloud SDK documentation for JavaScript](https://sap.github.io/cloud-sdk/docs/js/tutorials/getting-started/introduction)
6 |
7 | * [Access SAP Business Application Studio as a remote from Visual Studio Code / Codespaces](https://blogs.sap.com/2023/04/28/access-sap-business-application-studio-as-a-remote-from-visual-studio-code)
8 |
9 | * [SAP Cloud SDK repos for JavaScript](https://github.com/SAP/cloud-sdk-js)
10 |
11 | * [SAP Cloud SDK for JavaScript API documentation](https://sap.github.io/cloud-sdk/api/v2/index.html)
12 |
13 | * [.NET speaks OData too – how to implement Azure App Service with SAP Gateway](https://github.com/MartinPankraz/AzureSAPODataReader)
14 |
15 | * [Azure API Management policy for SAP Principal Propagation](https://github.com/Azure/api-management-policy-snippets/blob/master/examples/Request%20OAuth2%20access%20token%20from%20SAP%20using%20AAD%20JWT%20token.xml)
16 |
17 | ## Related efforts and repos🖇️
18 |
19 | * [Azure SDK for SAP OData](https://github.com/Azure/azure-sdk-for-sap-odata)
20 |
21 | * [Visual Studio extension for generating client code for OData Services](https://learn.microsoft.com/odata/connectedservice/getting-started)
22 |
23 | * [OData CLI](https://learn.microsoft.com/odata/odatacli/getting-started)
24 |
25 | * [.NET project showcasing integration of Azure AD with Azure API Management for SAP OData consumption leveraging Principal Propagation](https://github.com/MartinPankraz/AzureSAPODataReader)
26 |
27 | * [OData to OpenAPI converter](https://aka.ms/ODataOpenAPI)
28 |
29 | * [SAP ABAP OpenAPI UI](https://blogs.sap.com/2022/03/31/abap-openapi-ui-v2-a-long-overdue-update/)
30 |
31 | * [Azure Developer CLI](https://github.com/Azure/azure-dev)
32 |
--------------------------------------------------------------------------------
/documentation/DEPLOYMENT-VSCODE.md:
--------------------------------------------------------------------------------
1 | # Deployment via VS Code Extension
2 |
3 | In this example we use the [Azure App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) for VS Code to deploy the project. Learn more about [this process on Microsoft learn](https://learn.microsoft.com/training/modules/create-publish-webapp-app-service-vs-code/5-exercise-publish-app-azure-app-service-vs-code?pivots=nodeexpress).
4 |
5 | 1. Create an Azure App Service with Node.js 18 LTS and Linux using the [VS Code extension for Azure](https://code.visualstudio.com/docs/azure/extensions) or use below button.
6 | 2. Maintain or upload environment variables in the [Azure App Service configuration](https://learn.microsoft.com/azure/app-service/configure-common?tabs=portal#configure-app-settings) - just like you did for the `.env` file for local execution in the previous section.
7 | 3. Deploy to Web App from VS Code or GitHub Codespaces (right click in the explorer on the project folder and select "Deploy to Web App...").
8 | 4. Browse your new app powered by the SAP Cloud SDK (it takes a while the first time).
9 |
10 | [](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fapp-service-javascript-sap-cloud-sdk-quickstart%2Fmain%2Ftemplates%2Fazuredeploy.json)
11 |
--------------------------------------------------------------------------------
/hooks/deleteAppRegistrations.ps1:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script is part of the sample's workflow for configuring App Registrations
4 | # in Azure AD and saving the appropriate values in Key Vault, and Azure App Config Service
5 | # so that the application can authenticate users. Note that an app registration is
6 | # something you'll want to set up once, and reuse for every version of the web app
7 | # that you deploy. You can learn more about app registrations at
8 | # https://learn.microsoft.com/en-us/azure/active-directory/develop/application-model
9 | #
10 | # If you do not have permission to create App Registrations consider
11 | # sharing this script, or something similar, with your administrators to help them
12 | # set up the variables you need to integrate with Azure AD
13 | #
14 | # This code may be repurposed for your scenario as desired
15 | # but is not covered by the guidance in this content.
16 |
17 | # Using Azure CLI command to create an app registration on Entra ID: https://learn.microsoft.com/cli/azure/ad/app?view=azure-cli-latest
18 | if ($env:USE_EntraIDAuthentication -eq "false") {
19 |
20 | Write-Output "Skipping app registration delete because USE_EntraIDAuthentication is set to false"
21 | exit 0
22 |
23 | }
24 |
25 | Write-Output "Deleting app registration for web app using object id"
26 |
27 | # Get Object ID of app registration
28 |
29 | ###### Figure out how to get the object id of the app registration when AZD clears the .ENV file before this script runs
30 | #$APP_METADATA = az ad app list --display-name $env:WEB_APP_NAME | ConvertFrom-Json
31 | #$OBJECT_ID = $APP_METADATA.id
32 | #az ad app delete --id $OBJECT_ID
33 |
34 | # all done
35 | exit 0
--------------------------------------------------------------------------------
/infra-btpsa/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/SAP-samples/btp-setup-automator/main/libs/btpsa-parameters.json",
3 | "usecasefile": "usecase.json",
4 | "region": "eu20",
5 | "globalaccount": "ID of your Global Account",
6 | "myemail": "Enter your email address here",
7 | "loginmethod": "basicAuthentication",
8 | "subaccountname": "SAP-Cloud-SDK-Quickstart",
9 | "cfspacename": "development",
10 | "prunesubaccount": false
11 | }
--------------------------------------------------------------------------------
/infra-btpsa/usecase.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/SAP-samples/btp-setup-automator/main/libs/btpsa-usecase.json",
3 | "aboutThisUseCase": {
4 | "name": "SAP Cloud SDK Quickstart",
5 | "description": "This usecase provides all necessary information to create and deploy a SAP Cloud SDK based Node.js app a SAP BTP account to Cloud Foundry.",
6 | "author": "christian.lechner@sap.com",
7 | "testStatus": "tested successfully",
8 | "usageStatus": "READY TO BE USED",
9 | "relatedLinks": [
10 | "https://github.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart"
11 | ]
12 | },
13 | "services": [
14 | {
15 | "name": "cloudfoundry",
16 | "plan": "free",
17 | "category": "ENVIRONMENT"
18 | },
19 | {
20 | "name": "xsuaa",
21 | "instancename": "xsuaaquickstart",
22 | "plan": "application",
23 | "category": "SERVICE"
24 | },
25 | {
26 | "name": "destination",
27 | "instancename": "destinationquickstart",
28 | "plan": "lite",
29 | "category": "SERVICE",
30 | "parameters": {
31 | "HTML5Runtime_enabled": "true",
32 | "init_data": {
33 | "subaccount": {
34 | "existing_destinations_policy": "fail",
35 | "destinations": [
36 | {
37 | "Name": "S4HANACloudSandbox",
38 | "Description": "SAP S/4HANA Cloud Sandbox",
39 | "Type": "HTTP",
40 | "URL": "https://sandbox.api.sap.com/s4hanacloud",
41 | "Authentication": "BasicAuthentication",
42 | "ProxyType": "Internet",
43 | "User": "ODATA_USERNAME",
44 | "Password": "ODATA_USERPWD"
45 | }
46 | ]
47 | }
48 | }
49 | }
50 | },
51 | {
52 | "category": "SERVICE",
53 | "name": "privatelink",
54 | "plan": "standard",
55 | "entitleonly": true
56 | }
57 | ],
58 | "executeAfterAccountSetup": [
59 | {
60 | "description": "Building application assets",
61 | "command": "cd /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/src/api && npm ci && npm run build "
62 | },
63 | {
64 | "description": "Deploying the application",
65 | "command": "cd /workspaces/app-service-javascript-sap-cloud-sdk-quickstart/src/api && cf push cloudsdkapp"
66 | },
67 | {
68 | "description": "YOUR MANUAL TODO (Private Link Configuration)",
69 | "command": "echo '- Create service instance for Private Link service'"
70 | }
71 | ],
72 | "executeToPruneUseCase": [
73 | {
74 | "description": "Delete the application",
75 | "command": "cf delete cloudsdkapp -r -f"
76 | }
77 | ]
78 | }
--------------------------------------------------------------------------------
/infra-terraform/main.tfvars.json:
--------------------------------------------------------------------------------
1 | {
2 | "location": "${AZURE_LOCATION}",
3 | "environment_name": "${AZURE_ENV_NAME}",
4 | "principal_id": "${AZURE_PRINCIPAL_ID}"
5 | }
6 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim-api/apim-api.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 |
14 | data "azurerm_api_management" "apim" {
15 | name = var.name
16 | resource_group_name = var.rg_name
17 | }
18 |
19 | # ------------------------------------------------------------------------------------------------------
20 | # Deploy apim-api service
21 | # ------------------------------------------------------------------------------------------------------
22 | resource "azurerm_api_management_api" "api" {
23 | name = var.api_name
24 | resource_group_name = var.rg_name
25 | api_management_name = data.azurerm_api_management.apim.name
26 | revision = "1"
27 | display_name = var.api_display_name
28 | path = var.api_path
29 | protocols = ["https"]
30 | service_url = var.api_backend_url
31 | subscription_required = false
32 |
33 | import {
34 | content_format = "openapi"
35 | content_value = file("${path.module}/../../../src/api/openapi.yaml")
36 | }
37 | }
38 |
39 | resource "azurerm_api_management_api_policy" "policies" {
40 | api_name = azurerm_api_management_api.api.name
41 | api_management_name = azurerm_api_management_api.api.api_management_name
42 | resource_group_name = var.rg_name
43 |
44 | xml_content = replace(file("${path.module}/apim-api-policy.xml"), "{origin}", var.web_front_end_url)
45 | }
46 |
47 | resource "azurerm_api_management_api_diagnostic" "diagnostics" {
48 | identifier = "applicationinsights"
49 | resource_group_name = var.rg_name
50 | api_management_name = azurerm_api_management_api.api.api_management_name
51 | api_name = azurerm_api_management_api.api.name
52 | api_management_logger_id = var.api_management_logger_id
53 |
54 | sampling_percentage = 100.0
55 | always_log_errors = true
56 | log_client_ip = true
57 | verbosity = "verbose"
58 | http_correlation_protocol = "W3C"
59 |
60 | frontend_request {
61 | body_bytes = 1024
62 | headers_to_log = [
63 | "content-type",
64 | "accept",
65 | "origin",
66 | ]
67 | }
68 |
69 | frontend_response {
70 | body_bytes = 1024
71 | headers_to_log = [
72 | "content-type",
73 | "content-length",
74 | "origin",
75 | ]
76 | }
77 |
78 | backend_request {
79 | body_bytes = 1024
80 | headers_to_log = [
81 | "content-type",
82 | "accept",
83 | "origin",
84 | ]
85 | }
86 |
87 | backend_response {
88 | body_bytes = 1024
89 | headers_to_log = [
90 | "content-type",
91 | "content-length",
92 | "origin",
93 | ]
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim-api/apim-api_output.tf:
--------------------------------------------------------------------------------
1 | output "SERVICE_API_URI" {
2 | value = "${data.azurerm_api_management.apim.gateway_url}/${var.api_path}"
3 | }
4 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim-api/apim-api_variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | type = string
3 | }
4 |
5 | variable "rg_name" {
6 | description = "The name of the resource group to deploy resources into"
7 | type = string
8 | }
9 |
10 | variable "api_management_logger_id" {
11 | description = "The name of the resource application insights"
12 | type = string
13 | }
14 |
15 | variable "web_front_end_url" {
16 | description = "The url of the web"
17 | type = string
18 | }
19 |
20 | variable "api_backend_url" {
21 | description = "Absolute URL of the backend service implementing this API."
22 | type = string
23 | }
24 |
25 | variable "api_name" {
26 | description = "Resource name to uniquely identify this API within the API Management service instance"
27 | type = string
28 | }
29 |
30 | variable "api_display_name" {
31 |
32 | description = "The Display Name of the API"
33 | type = string
34 | }
35 |
36 | variable "api_path" {
37 | description = "Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API."
38 | type = string
39 | }
40 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim/apim.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 |
14 | data "azurerm_application_insights" "appinsights"{
15 | name = var.application_insights_name
16 | resource_group_name = var.rg_name
17 | }
18 | # ------------------------------------------------------------------------------------------------------
19 | # Deploy api management service
20 | # ------------------------------------------------------------------------------------------------------
21 |
22 | # Create a new APIM instance
23 | resource "azurerm_api_management" "apim" {
24 | name = var.name
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | publisher_name = var.publisher_name
28 | publisher_email = var.publisher_email
29 | tags = var.tags
30 | sku_name = "${var.sku}_${(var.sku == "Consumption") ? 0 : ((var.sku == "Developer") ? 1 : var.skuCount)}"
31 | identity {
32 | type = "SystemAssigned"
33 | }
34 | }
35 |
36 | # Create Logger
37 | resource "azurerm_api_management_logger" "logger" {
38 | name = "app-insights-logger"
39 | api_management_name = azurerm_api_management.apim.name
40 | resource_group_name = var.rg_name
41 |
42 | application_insights {
43 | instrumentation_key = data.azurerm_application_insights.appinsights.instrumentation_key
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim/apim_output.tf:
--------------------------------------------------------------------------------
1 | output "APIM_SERVICE_NAME" {
2 | value = azurerm_api_management.apim.name
3 | }
4 |
5 | output "API_MANAGEMENT_LOGGER_ID" {
6 | value = azurerm_api_management_logger.logger.id
7 | }
8 |
--------------------------------------------------------------------------------
/infra-terraform/modules/apim/apim_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | description = "A list of tags used for deployed services."
13 | type = map(string)
14 | }
15 |
16 | variable "sku" {
17 | description = "The pricing tier of this API Management service."
18 | type = string
19 | default = "Consumption"
20 | }
21 |
22 | variable "application_insights_name" {
23 | description = "Azure Application Insights Name."
24 | type = string
25 | }
26 |
27 | variable "skuCount" {
28 | description = "The instance size of this API Management service. @allowed([ 0, 1, 2 ])"
29 | type = string
30 | default = "0"
31 | }
32 |
33 | variable "name" {
34 | type = string
35 | }
36 |
37 | variable "publisher_email" {
38 | description = "The email address of the owner of the service."
39 | type = string
40 | default = "noreply@microsoft.com"
41 | }
42 |
43 | variable "publisher_name" {
44 | description = "The name of the owner of the service"
45 | type = string
46 | default = "n/a"
47 | }
48 |
--------------------------------------------------------------------------------
/infra-terraform/modules/applicationinsights/applicationinsights_output.tf:
--------------------------------------------------------------------------------
1 | output "APPLICATIONINSIGHTS_CONNECTION_STRING" {
2 | value = azurerm_application_insights.applicationinsights.connection_string
3 | sensitive = true
4 | }
5 |
6 | output "APPLICATIONINSIGHTS_NAME" {
7 | value = azurerm_application_insights.applicationinsights.name
8 | sensitive = false
9 | }
10 |
11 | output "APPLICATIONINSIGHTS_INSTRUMENTATION_KEY" {
12 | value = azurerm_application_insights.applicationinsights.instrumentation_key
13 | sensitive = true
14 | }
15 |
--------------------------------------------------------------------------------
/infra-terraform/modules/applicationinsights/applicationinsights_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "environment_name" {
12 | description = "The name of the environment to be deployed"
13 | type = string
14 | }
15 |
16 | variable "workspace_id" {
17 | description = "The name of the Azure log analytics workspace"
18 | type = string
19 | }
20 |
21 | variable "tags" {
22 | description = "A list of tags used for deployed services."
23 | type = map(string)
24 | }
25 |
26 | variable "resource_token" {
27 | description = "A suffix string to centrally mitigate resource name collisions."
28 | type = string
29 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/appservicenode/appservicenode.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 | # ------------------------------------------------------------------------------------------------------
14 | # Deploy app service web app
15 | # ------------------------------------------------------------------------------------------------------
16 | resource "azurecaf_name" "web_name" {
17 | name = "${var.service_name}-${var.resource_token}"
18 | resource_type = "azurerm_app_service"
19 | random_length = 0
20 | clean_input = true
21 | }
22 |
23 | resource "azurerm_linux_web_app" "web" {
24 | name = azurecaf_name.web_name.result
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | service_plan_id = var.appservice_plan_id
28 | https_only = true
29 | tags = var.tags
30 |
31 | site_config {
32 | always_on = true
33 | ftps_state = "FtpsOnly"
34 | app_command_line = var.app_command_line
35 | application_stack {
36 | node_version = var.node_version
37 | }
38 | }
39 |
40 | app_settings = var.app_settings
41 |
42 | dynamic "identity" {
43 | for_each = { for k, v in var.identity : k => v if var.identity != [] }
44 | content {
45 | type = identity.value["type"]
46 | }
47 | }
48 |
49 | logs {
50 | application_logs {
51 | file_system_level = "Verbose"
52 | }
53 | detailed_error_messages = true
54 | failed_request_tracing = true
55 | http_logs {
56 | file_system {
57 | retention_in_days = 1
58 | retention_in_mb = 35
59 | }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/appservicenode/appservicenode_output.tf:
--------------------------------------------------------------------------------
1 | output "URI" {
2 | value = "https://${azurerm_linux_web_app.web.default_hostname}"
3 | }
4 |
5 | output "IDENTITY_PRINCIPAL_ID" {
6 | value = length(azurerm_linux_web_app.web.identity) == 0 ? "" : azurerm_linux_web_app.web.identity.0.principal_id
7 | sensitive = true
8 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/appservicenode/appservicenode_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "appservice_plan_id" {
12 | description = "The id of the appservice plan to use."
13 | type = string
14 | }
15 |
16 | variable "service_name" {
17 | description = "A name to reflect the type of the app service e.g: web, api."
18 | type = string
19 | }
20 |
21 | variable "app_settings" {
22 | description = "A list of app settings pairs to be assigned to the app service"
23 | type = map(string)
24 | }
25 |
26 | variable "identity" {
27 | description = "A list of application identity"
28 | type = list(any)
29 | default = []
30 | }
31 |
32 | variable "app_command_line" {
33 | description = "The cmd line to configure the app to run."
34 | type = string
35 | }
36 |
37 | variable "tags" {
38 | description = "A list of tags used for deployed services."
39 | type = map(string)
40 | }
41 |
42 | variable "resource_token" {
43 | description = "A suffix string to centrally mitigate resource name collisions."
44 | type = string
45 | }
46 |
47 | variable "node_version" {
48 | description = "the application stack node version to set for the app service."
49 | type = string
50 | default = "16-lts"
51 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/appserviceplan/appserviceplan.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 | # ------------------------------------------------------------------------------------------------------
14 | # Deploy app service plan
15 | # ------------------------------------------------------------------------------------------------------
16 | resource "azurecaf_name" "plan_name" {
17 | name = var.resource_token
18 | resource_type = "azurerm_app_service_plan"
19 | random_length = 0
20 | clean_input = true
21 | }
22 |
23 | resource "azurerm_service_plan" "plan" {
24 | name = azurecaf_name.plan_name.result
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | os_type = var.os_type
28 | sku_name = var.sku_name
29 |
30 | tags = var.tags
31 | }
32 |
--------------------------------------------------------------------------------
/infra-terraform/modules/appserviceplan/appserviceplan_output.tf:
--------------------------------------------------------------------------------
1 | output "APPSERVICE_PLAN_ID" {
2 | value = azurerm_service_plan.plan.id
3 | sensitive = true
4 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/appserviceplan/appserviceplan_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | description = "A list of tags used for deployed services."
13 | type = map(string)
14 | }
15 |
16 | variable "resource_token" {
17 | description = "A suffix string to centrally mitigate resource name collisions."
18 | type = string
19 | }
20 |
21 | variable "sku_name" {
22 | description = "The SKU for the plan."
23 | type = string
24 | default = "B1"
25 | }
26 |
27 | variable "os_type" {
28 | description = "The O/S type for the App Services to be hosted in this plan."
29 | type = string
30 | default = "Linux"
31 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/cosmos/cosmos.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 | # ------------------------------------------------------------------------------------------------------
14 | # Deploy cosmos db account
15 | # ------------------------------------------------------------------------------------------------------
16 | resource "azurecaf_name" "db_acc_name" {
17 | name = var.resource_token
18 | resource_type = "azurerm_cosmosdb_account"
19 | random_length = 0
20 | clean_input = true
21 | }
22 |
23 | resource "azurerm_cosmosdb_account" "db" {
24 | name = azurecaf_name.db_acc_name.result
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | offer_type = "Standard"
28 | kind = "MongoDB"
29 | enable_automatic_failover = false
30 | enable_multiple_write_locations = false
31 | mongo_server_version = "4.0"
32 | tags = var.tags
33 |
34 | capabilities {
35 | name = "EnableServerless"
36 | }
37 |
38 | lifecycle {
39 | ignore_changes = [capabilities]
40 | }
41 | consistency_policy {
42 | consistency_level = "Session"
43 | }
44 |
45 | geo_location {
46 | location = var.location
47 | failover_priority = 0
48 | zone_redundant = false
49 | }
50 | }
51 |
52 | # ------------------------------------------------------------------------------------------------------
53 | # Deploy cosmos mongo db and collections
54 | # ------------------------------------------------------------------------------------------------------
55 | resource "azurerm_cosmosdb_mongo_database" "mongodb" {
56 | name = "Todo"
57 | resource_group_name = azurerm_cosmosdb_account.db.resource_group_name
58 | account_name = azurerm_cosmosdb_account.db.name
59 | }
60 |
61 | resource "azurerm_cosmosdb_mongo_collection" "list" {
62 | name = "TodoList"
63 | resource_group_name = azurerm_cosmosdb_account.db.resource_group_name
64 | account_name = azurerm_cosmosdb_account.db.name
65 | database_name = azurerm_cosmosdb_mongo_database.mongodb.name
66 | shard_key = "_id"
67 |
68 |
69 | index {
70 | keys = ["_id"]
71 | unique = true
72 | }
73 | }
74 |
75 | resource "azurerm_cosmosdb_mongo_collection" "item" {
76 | name = "TodoItem"
77 | resource_group_name = azurerm_cosmosdb_account.db.resource_group_name
78 | account_name = azurerm_cosmosdb_account.db.name
79 | database_name = azurerm_cosmosdb_mongo_database.mongodb.name
80 | shard_key = "_id"
81 |
82 | index {
83 | keys = ["_id"]
84 | unique = true
85 | }
86 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/cosmos/cosmos_output.tf:
--------------------------------------------------------------------------------
1 | output "AZURE_COSMOS_CONNECTION_STRING" {
2 | value = azurerm_cosmosdb_account.db.connection_strings[0]
3 | sensitive = true
4 | }
5 |
6 | output "AZURE_COSMOS_DATABASE_NAME" {
7 | value = azurerm_cosmosdb_mongo_database.mongodb.name
8 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/cosmos/cosmos_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | description = "A list of tags used for deployed services."
13 | type = map(string)
14 | }
15 |
16 | variable "resource_token" {
17 | description = "A suffix string to centrally mitigate resource name collisions."
18 | type = string
19 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/keyvault/keyvault.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 |
14 | data "azurerm_client_config" "current" {}
15 | # ------------------------------------------------------------------------------------------------------
16 | # DEPLOY AZURE KEYVAULT
17 | # ------------------------------------------------------------------------------------------------------
18 | resource "azurecaf_name" "kv_name" {
19 | name = var.resource_token
20 | resource_type = "azurerm_key_vault"
21 | random_length = 0
22 | clean_input = true
23 | }
24 |
25 | resource "azurerm_key_vault" "kv" {
26 | name = azurecaf_name.kv_name.result
27 | location = var.location
28 | resource_group_name = var.rg_name
29 | tenant_id = data.azurerm_client_config.current.tenant_id
30 | purge_protection_enabled = false
31 | sku_name = "standard"
32 |
33 | tags = var.tags
34 | }
35 |
36 | resource "azurerm_key_vault_access_policy" "app" {
37 | count = length(var.access_policy_object_ids)
38 | key_vault_id = azurerm_key_vault.kv.id
39 | tenant_id = data.azurerm_client_config.current.tenant_id
40 | object_id = var.access_policy_object_ids[count.index]
41 |
42 | secret_permissions = [
43 | "Get",
44 | "Set",
45 | "List",
46 | "Delete",
47 | ]
48 | }
49 |
50 | resource "azurerm_key_vault_access_policy" "user" {
51 | count = var.principal_id == "" ? 0 : 1
52 | key_vault_id = azurerm_key_vault.kv.id
53 | tenant_id = data.azurerm_client_config.current.tenant_id
54 | object_id = var.principal_id
55 |
56 | secret_permissions = [
57 | "Get",
58 | "Set",
59 | "List",
60 | "Delete",
61 | "Purge"
62 | ]
63 | }
64 |
65 | resource "azurerm_key_vault_secret" "secrets" {
66 | count = length(var.secrets)
67 | name = var.secrets[count.index].name
68 | value = var.secrets[count.index].value
69 | key_vault_id = azurerm_key_vault.kv.id
70 | depends_on = [
71 | azurerm_key_vault_access_policy.user,
72 | azurerm_key_vault_access_policy.app
73 | ]
74 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/keyvault/keyvault_output.tf:
--------------------------------------------------------------------------------
1 | output "AZURE_KEY_VAULT_ENDPOINT" {
2 | value = azurerm_key_vault.kv.vault_uri
3 | sensitive = true
4 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/keyvault/keyvault_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | description = "A list of tags used for deployed services."
13 | type = map(string)
14 | }
15 |
16 | variable "resource_token" {
17 | description = "A suffix string to centrally mitigate resource name collisions."
18 | type = string
19 | }
20 |
21 | variable "principal_id" {
22 | description = "The Id of the service principal to add to deployed keyvault access policies"
23 | sensitive = true
24 | type = string
25 | }
26 |
27 | variable "access_policy_object_ids" {
28 | description = "A list of object ids to be be added to the keyvault access policies"
29 | type = list(string)
30 | sensitive = true
31 | default = []
32 | }
33 |
34 | variable "secrets" {
35 | description = "A list of secrets to be added to the keyvault"
36 | type = list(object({
37 | name = string
38 | value = string
39 | }))
40 | sensitive = true
41 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/loganalytics/loganalytics.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 | # ------------------------------------------------------------------------------------------------------
14 | # Deploy log analytics workspace
15 | # ------------------------------------------------------------------------------------------------------
16 | resource "azurecaf_name" "workspace_name" {
17 | name = var.resource_token
18 | resource_type = "azurerm_log_analytics_workspace"
19 | random_length = 0
20 | clean_input = true
21 | }
22 |
23 | resource "azurerm_log_analytics_workspace" "workspace" {
24 | name = azurecaf_name.workspace_name.result
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | sku = "PerGB2018"
28 | retention_in_days = 30
29 | tags = var.tags
30 | }
31 |
--------------------------------------------------------------------------------
/infra-terraform/modules/loganalytics/loganalytics_output.tf:
--------------------------------------------------------------------------------
1 | output "LOGANALYTICS_WORKSPACE_ID" {
2 | value = azurerm_log_analytics_workspace.workspace.id
3 | }
--------------------------------------------------------------------------------
/infra-terraform/modules/loganalytics/loganalytics_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "resource_token" {
12 | description = "A suffix string to centrally mitigate resource name collisions."
13 | type = string
14 | }
15 |
16 | variable "tags" {
17 | description = "A list of tags used for deployed services."
18 | type = map(string)
19 | }
--------------------------------------------------------------------------------
/infra-terraform/modules_local/apim-api/apim-api.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | # azapi = {
12 | # source = "Azure/azapi"
13 | # version = "~>1.6.0"
14 | # }
15 | }
16 | }
17 |
18 | locals {
19 | appNameforAppProperties = var.api_app_name != "" ? var.api_app_name : "placeholdername"
20 | }
21 |
22 | # ------------------------------------------------------------------------------------------------------
23 | # Read existing resources from different resource groups
24 | # ------------------------------------------------------------------------------------------------------
25 | data "azurerm_application_insights" "appinsights" {
26 | name = var.application_insights_name
27 | resource_group_name = var.rg_name_app
28 | }
29 |
30 | data "azurerm_api_management" "apim" {
31 | name = var.name
32 | resource_group_name = var.rg_name_apim
33 | }
34 |
35 | # ------------------------------------------------------------------------------------------------------
36 | # Deploy apim-api service
37 | # ------------------------------------------------------------------------------------------------------
38 | resource "azurerm_api_management_api" "api" {
39 | name = var.api_name
40 | resource_group_name = var.rg_name_apim
41 | api_management_name = data.azurerm_api_management.apim.name
42 | revision = "1"
43 | display_name = var.api_display_name
44 | path = var.api_path
45 | protocols = ["https"]
46 | service_url = var.api_backend_url
47 | subscription_required = false
48 | api_type = "http"
49 | description = var.api_description
50 |
51 | import {
52 | content_format = "openapi"
53 | content_value = file("${path.module}/../../../src/api/API_BUSINESS_PARTNER.openapi.json")
54 | }
55 | }
56 |
57 | resource "azurerm_api_management_api_policy" "policies" {
58 | api_name = azurerm_api_management_api.api.name
59 | api_management_name = azurerm_api_management_api.api.api_management_name
60 | resource_group_name = var.rg_name_apim
61 |
62 | xml_content = file("${path.module}/apim-api-policy.xml")
63 | }
64 |
65 | resource "azurerm_api_management_logger" "apimLogger" {
66 | name = "apimlogger"
67 | api_management_name = data.azurerm_api_management.apim.name
68 | resource_group_name = var.rg_name_apim
69 | resource_id = data.azurerm_application_insights.appinsights.id
70 |
71 | application_insights {
72 | instrumentation_key = data.azurerm_application_insights.appinsights.instrumentation_key
73 | }
74 | }
75 |
76 | #resource "azapi_resource" "api_app_properties" {
77 | # type = "Microsoft.Web/sites/config@2022-03-01"
78 | # name = "${local.appNameforAppProperties}/web"
79 | # parent_id = data.azurerm_api_management.apim.id
80 | # body = jsonencode({
81 | # properties = {
82 | # apiManagementConfig = {
83 | # id = "${data.azurerm_api_management.apim.id}/apis/${var.api_name}"
84 | # }
85 | # }
86 | # })
87 | #}
88 |
--------------------------------------------------------------------------------
/infra-terraform/modules_local/apim-api/apim-api_output.tf:
--------------------------------------------------------------------------------
1 | output "SERVICE_API_URI" {
2 | value = "${data.azurerm_api_management.apim.gateway_url}/${var.api_path}"
3 | }
4 |
--------------------------------------------------------------------------------
/infra-terraform/modules_local/apim-api/apim-api_variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "The name of the API Management Service"
3 | type = string
4 | }
5 |
6 | variable "rg_name_apim" {
7 | description = "The name of the resource group of the API management"
8 | type = string
9 | }
10 |
11 | variable "rg_name_app" {
12 | description = "The name of the resource group of the application"
13 | type = string
14 | }
15 |
16 | variable "api_name" {
17 | description = "Resource name to uniquely identify this API within the API Management service instance"
18 | type = string
19 | }
20 |
21 | variable "api_display_name" {
22 | description = "The Display Name of the API"
23 | type = string
24 | }
25 |
26 | variable "api_description" {
27 | description = "Description of the API. May include HTML formatting tags."
28 | type = string
29 | }
30 |
31 | variable "api_path" {
32 | description = "Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API."
33 | type = string
34 | }
35 |
36 | variable "api_backend_url" {
37 | description = "Absolute URL of the backend service implementing this API."
38 | type = string
39 | }
40 |
41 | variable "application_insights_name" {
42 | description = "Azure Application Insights Name."
43 | type = string
44 | }
45 |
46 | variable "api_app_name" {
47 | description = "Resource name for backend Web App or Function App"
48 | type = string
49 | default = ""
50 | }
51 |
--------------------------------------------------------------------------------
/infra-terraform/modules_local/appservicenode/appservicenode.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | version = "~>3.47.0"
5 | source = "hashicorp/azurerm"
6 | }
7 | azurecaf = {
8 | source = "aztfmod/azurecaf"
9 | version = "~>1.2.15"
10 | }
11 | }
12 | }
13 | # ------------------------------------------------------------------------------------------------------
14 | # Deploy app service web app
15 | # ------------------------------------------------------------------------------------------------------
16 | resource "azurecaf_name" "web_name" {
17 | name = "${var.service_name}-${var.resource_token}"
18 | resource_type = "azurerm_app_service"
19 | random_length = 0
20 | clean_input = true
21 | }
22 |
23 | resource "azurerm_linux_web_app" "web" {
24 | name = azurecaf_name.web_name.result
25 | location = var.location
26 | resource_group_name = var.rg_name
27 | service_plan_id = var.appservice_plan_id
28 | https_only = true
29 | tags = var.tags
30 |
31 | site_config {
32 | ftps_state = "FtpsOnly"
33 | app_command_line = var.app_command_line
34 | application_stack {
35 | node_version = var.node_version
36 | }
37 | always_on = var.always_on
38 | health_check_path = var.health_check_path
39 | use_32_bit_worker = var.use_32_bit_worker
40 | }
41 |
42 | app_settings = var.app_settings
43 |
44 | dynamic "identity" {
45 | for_each = { for k, v in var.identity : k => v if var.identity != [] }
46 | content {
47 | type = identity.value["type"]
48 | }
49 | }
50 |
51 | logs {
52 | application_logs {
53 | file_system_level = "Verbose"
54 | }
55 | detailed_error_messages = true
56 | failed_request_tracing = true
57 | http_logs {
58 | file_system {
59 | retention_in_days = 1
60 | retention_in_mb = 35
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/infra-terraform/modules_local/appservicenode/appservicenode_output.tf:
--------------------------------------------------------------------------------
1 | output "URI" {
2 | value = "https://${azurerm_linux_web_app.web.default_hostname}"
3 | }
4 |
5 | output "IDENTITY_PRINCIPAL_ID" {
6 | value = length(azurerm_linux_web_app.web.identity) == 0 ? "" : azurerm_linux_web_app.web.identity.0.principal_id
7 | sensitive = true
8 | }
--------------------------------------------------------------------------------
/infra-terraform/modules_local/appservicenode/appservicenode_variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "rg_name" {
7 | description = "The name of the resource group to deploy resources into"
8 | type = string
9 | }
10 |
11 | variable "appservice_plan_id" {
12 | description = "The id of the appservice plan to use."
13 | type = string
14 | }
15 |
16 | variable "service_name" {
17 | description = "A name to reflect the type of the app service e.g: web, api."
18 | type = string
19 | }
20 |
21 | variable "app_settings" {
22 | description = "A list of app settings pairs to be assigned to the app service"
23 | type = map(string)
24 | }
25 |
26 | variable "identity" {
27 | description = "A list of application identity"
28 | type = list(any)
29 | default = []
30 | }
31 |
32 | variable "app_command_line" {
33 | description = "The cmd line to configure the app to run."
34 | type = string
35 | }
36 |
37 | variable "tags" {
38 | description = "A list of tags used for deployed services."
39 | type = map(string)
40 | }
41 |
42 | variable "resource_token" {
43 | description = "A suffix string to centrally mitigate resource name collisions."
44 | type = string
45 | }
46 |
47 | variable "node_version" {
48 | description = "the application stack node version to set for the app service."
49 | type = string
50 | default = "18-lts"
51 | }
52 |
53 | variable "always_on" {
54 | description = "The always on setting for the app service."
55 | type = bool
56 | default = true
57 | }
58 |
59 | variable "health_check_path" {
60 | description = "The path to the health check endpoint"
61 | type = string
62 | default = ""
63 | }
64 |
65 | variable "use_32_bit_worker" {
66 | description = "The use 32 bit worker setting for the app service."
67 | type = bool
68 | default = false
69 | }
--------------------------------------------------------------------------------
/infra-terraform/output.tf:
--------------------------------------------------------------------------------
1 | output "APPLICATIONINSIGHTS_CONNECTION_STRING" {
2 | value = module.applicationinsights.APPLICATIONINSIGHTS_CONNECTION_STRING
3 | sensitive = true
4 | }
5 |
6 | output "AZURE_KEY_VAULT_ENDPOINT" {
7 | value = module.keyvault.AZURE_KEY_VAULT_ENDPOINT
8 | sensitive = true
9 | }
10 |
11 | output "AZURE_LOCATION" {
12 | value = var.location
13 | }
14 |
15 | output "USE_APIM" {
16 | value = var.useAPIM
17 | }
18 |
19 | output "SAP_CLOUD_SDK_API_URL" {
20 | value = module.api.URI
21 | }
22 |
23 | output "SAP_CLOUD_SDK_API_APPLICATIONINSIGHTS_CONNECTION_STRING" {
24 | value = module.applicationinsights.APPLICATIONINSIGHTS_CONNECTION_STRING
25 | sensitive = true
26 | }
27 |
--------------------------------------------------------------------------------
/infra-terraform/provider.tf:
--------------------------------------------------------------------------------
1 | #Set the terraform required version, and Configure the Azure Provider.Use local storage
2 |
3 | # Configure the Azure Provider
4 | terraform {
5 | required_version = ">= 1.1.7, < 2.0.0"
6 | required_providers {
7 | azurerm = {
8 | version = "~>3.47.0"
9 | source = "hashicorp/azurerm"
10 | }
11 | azurecaf = {
12 | source = "aztfmod/azurecaf"
13 | version = "~>1.2.15"
14 | }
15 | }
16 | }
17 |
18 | provider "azurerm" {
19 | features {
20 | key_vault {
21 | purge_soft_delete_on_destroy = false
22 | }
23 | resource_group {
24 | prevent_deletion_if_contains_resources = false
25 | }
26 | }
27 | }
28 |
29 | # Make client_id, tenant_id, subscription_id and object_id variables
30 | data "azurerm_client_config" "current" {}
--------------------------------------------------------------------------------
/infra-terraform/variables.tf:
--------------------------------------------------------------------------------
1 | variable "location" {
2 | description = "The supported Azure location where the resource deployed"
3 | type = string
4 | }
5 |
6 | variable "environment_name" {
7 | description = "The name of the azd environment to be deployed"
8 | type = string
9 | }
10 |
11 | variable "principal_id" {
12 | description = "The Id of the azd service principal to add to deployed keyvault access policies"
13 | type = string
14 | default = ""
15 | }
16 |
17 | // App specific parameters - provide the values via the main.parameters.json referencing e.g. environment parameters
18 | variable "sku_name" {
19 | description = "The name of the SKU used to create the key vault"
20 | type = string
21 | default = "F1"
22 | }
23 |
24 | variable "health_check_path" {
25 | description = "The path to the health check endpoint"
26 | type = string
27 | default = "/health"
28 | }
29 |
30 |
31 | variable "oDataUrl" {
32 | description = "SAP OData service URL"
33 | type = string
34 | default = "https://sandbox.api.sap.com/s4hanacloud"
35 | }
36 |
37 | variable "oDataUsername" {
38 | description = "SAP OData user name"
39 | type = string
40 | default = ""
41 | }
42 |
43 | variable "oDataUserpwd" {
44 | description = "SAP OData user password"
45 | type = string
46 | default = ""
47 | sensitive = true
48 | }
49 |
50 | variable "_APIKey" {
51 | description = "API Key"
52 | type = string
53 | default = ""
54 | sensitive = true
55 | }
56 |
57 | variable "ApiKeyHeaderName" {
58 | description = "API Key Header Name"
59 | type = string
60 | default = "APIKey"
61 | }
62 |
63 | variable "useAPIM" {
64 | description = "Flag to use Azure API Management to mediate the calls between the Web frontend and the SAP backend API"
65 | type = bool
66 | default = false
67 | }
68 |
69 | variable "apimResourceGroupName" {
70 | description = "Resource Group containing the existing API Management instance"
71 | type = string
72 | default = "DEMO-NEU-SAP-PM1"
73 | }
74 |
75 | variable "apimServiceName" {
76 | description = "Name of the existing API Management instance"
77 | type = string
78 | default = "demo-sap-apim"
79 | }
80 |
81 | variable "apimApiSAPBackendURL" {
82 | description = "Target URL of the SAP backend API fronted by the existing API Management"
83 | type = string
84 | default = "https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_BUSINESS_PARTNER"
85 | }
86 |
--------------------------------------------------------------------------------
/infra/app/api.bicep:
--------------------------------------------------------------------------------
1 | param name string
2 | param location string = resourceGroup().location
3 | param tags object = {}
4 |
5 | param allowedOrigins array = []
6 | param appCommandLine string = ''
7 | param applicationInsightsName string = ''
8 | param appServicePlanId string
9 | param appSettings object = {}
10 | param useAuthSettingsv2 bool = false
11 | param keyVaultName string
12 | param serviceName string = 'sap-cloud-sdk-api'
13 | param healthCheckPath string = '/health'
14 | param use32BitWorkerProcess bool = false
15 |
16 | param alwaysOn bool = true
17 |
18 | module api '../core_local/host/appservice.bicep' = {
19 | name: '${name}-app-module'
20 | params: {
21 | name: name
22 | location: location
23 | tags: union(tags, { 'azd-service-name': serviceName })
24 | allowedOrigins: allowedOrigins
25 | appCommandLine: appCommandLine
26 | applicationInsightsName: applicationInsightsName
27 | appServicePlanId: appServicePlanId
28 | appSettings: appSettings
29 | useAuthSettingsv2: useAuthSettingsv2
30 | keyVaultName: keyVaultName
31 | runtimeName: 'node'
32 | runtimeVersion: '20-lts'
33 | scmDoBuildDuringDeployment: true
34 | healthCheckPath: healthCheckPath
35 | use32BitWorkerProcess: use32BitWorkerProcess
36 | alwaysOn: alwaysOn
37 | }
38 | }
39 |
40 | output SERVICE_API_IDENTITY_PRINCIPAL_ID string = api.outputs.identityPrincipalId
41 | output SERVICE_API_NAME string = api.outputs.name
42 | output SERVICE_API_URI string = api.outputs.uri
43 |
--------------------------------------------------------------------------------
/infra/app/apim-api-policy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
28 |
29 |
30 |
31 |
32 |
33 | @(context.LastError.Source)
34 |
35 |
36 | @(context.LastError.Reason)
37 |
38 |
39 | @(context.LastError.Message)
40 |
41 |
42 | @(context.LastError.Scope)
43 |
44 |
45 | @(context.LastError.Section)
46 |
47 |
48 | @(context.LastError.Path)
49 |
50 |
51 | @(context.LastError.PolicyId)
52 |
53 |
54 | @(context.Response.StatusCode.ToString())
55 |
56 |
57 |
--------------------------------------------------------------------------------
/infra/core/ai/cognitiveservices.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cognitive Services instance.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 | @description('The custom subdomain name used to access the API. Defaults to the value of the name parameter.')
6 | param customSubDomainName string = name
7 | param deployments array = []
8 | param kind string = 'OpenAI'
9 |
10 | @allowed([ 'Enabled', 'Disabled' ])
11 | param publicNetworkAccess string = 'Enabled'
12 | param sku object = {
13 | name: 'S0'
14 | }
15 |
16 | param allowedIpRules array = []
17 | param networkAcls object = empty(allowedIpRules) ? {
18 | defaultAction: 'Allow'
19 | } : {
20 | ipRules: allowedIpRules
21 | defaultAction: 'Deny'
22 | }
23 |
24 | resource account 'Microsoft.CognitiveServices/accounts@2023-05-01' = {
25 | name: name
26 | location: location
27 | tags: tags
28 | kind: kind
29 | properties: {
30 | customSubDomainName: customSubDomainName
31 | publicNetworkAccess: publicNetworkAccess
32 | networkAcls: networkAcls
33 | }
34 | sku: sku
35 | }
36 |
37 | @batchSize(1)
38 | resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2023-05-01' = [for deployment in deployments: {
39 | parent: account
40 | name: deployment.name
41 | properties: {
42 | model: deployment.model
43 | raiPolicyName: contains(deployment, 'raiPolicyName') ? deployment.raiPolicyName : null
44 | }
45 | sku: contains(deployment, 'sku') ? deployment.sku : {
46 | name: 'Standard'
47 | capacity: 20
48 | }
49 | }]
50 |
51 | output endpoint string = account.properties.endpoint
52 | output id string = account.id
53 | output name string = account.name
54 |
--------------------------------------------------------------------------------
/infra/core/config/configstore.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure App Configuration store.'
2 |
3 | @description('The name for the Azure App Configuration store')
4 | param name string
5 |
6 | @description('The Azure region/location for the Azure App Configuration store')
7 | param location string = resourceGroup().location
8 |
9 | @description('Custom tags to apply to the Azure App Configuration store')
10 | param tags object = {}
11 |
12 | @description('Specifies the names of the key-value resources. The name is a combination of key and label with $ as delimiter. The label is optional.')
13 | param keyValueNames array = []
14 |
15 | @description('Specifies the values of the key-value resources.')
16 | param keyValueValues array = []
17 |
18 | @description('The principal ID to grant access to the Azure App Configuration store')
19 | param principalId string
20 |
21 | resource configStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' = {
22 | name: name
23 | location: location
24 | sku: {
25 | name: 'standard'
26 | }
27 | tags: tags
28 | }
29 |
30 | resource configStoreKeyValue 'Microsoft.AppConfiguration/configurationStores/keyValues@2023-03-01' = [for (item, i) in keyValueNames: {
31 | parent: configStore
32 | name: item
33 | properties: {
34 | value: keyValueValues[i]
35 | tags: tags
36 | }
37 | }]
38 |
39 | module configStoreAccess '../security/configstore-access.bicep' = {
40 | name: 'app-configuration-access'
41 | params: {
42 | configStoreName: name
43 | principalId: principalId
44 | }
45 | dependsOn: [configStore]
46 | }
47 |
48 | output endpoint string = configStore.properties.endpoint
49 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/cosmos-account.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cosmos DB account.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
7 | param keyVaultName string
8 |
9 | @allowed([ 'GlobalDocumentDB', 'MongoDB', 'Parse' ])
10 | param kind string
11 |
12 | resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = {
13 | name: name
14 | kind: kind
15 | location: location
16 | tags: tags
17 | properties: {
18 | consistencyPolicy: { defaultConsistencyLevel: 'Session' }
19 | locations: [
20 | {
21 | locationName: location
22 | failoverPriority: 0
23 | isZoneRedundant: false
24 | }
25 | ]
26 | databaseAccountOfferType: 'Standard'
27 | enableAutomaticFailover: false
28 | enableMultipleWriteLocations: false
29 | apiProperties: (kind == 'MongoDB') ? { serverVersion: '4.2' } : {}
30 | capabilities: [ { name: 'EnableServerless' } ]
31 | }
32 | }
33 |
34 | resource cosmosConnectionString 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
35 | parent: keyVault
36 | name: connectionStringKey
37 | properties: {
38 | value: cosmos.listConnectionStrings().connectionStrings[0].connectionString
39 | }
40 | }
41 |
42 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
43 | name: keyVaultName
44 | }
45 |
46 | output connectionStringKey string = connectionStringKey
47 | output endpoint string = cosmos.properties.documentEndpoint
48 | output id string = cosmos.id
49 | output name string = cosmos.name
50 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/mongo/cosmos-mongo-account.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cosmos DB for MongoDB account.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param keyVaultName string
7 | param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
8 |
9 | module cosmos '../../cosmos/cosmos-account.bicep' = {
10 | name: 'cosmos-account'
11 | params: {
12 | name: name
13 | location: location
14 | connectionStringKey: connectionStringKey
15 | keyVaultName: keyVaultName
16 | kind: 'MongoDB'
17 | tags: tags
18 | }
19 | }
20 |
21 | output connectionStringKey string = cosmos.outputs.connectionStringKey
22 | output endpoint string = cosmos.outputs.endpoint
23 | output id string = cosmos.outputs.id
24 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/mongo/cosmos-mongo-db.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cosmos DB for MongoDB account with a database.'
2 | param accountName string
3 | param databaseName string
4 | param location string = resourceGroup().location
5 | param tags object = {}
6 |
7 | param collections array = []
8 | param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
9 | param keyVaultName string
10 |
11 | module cosmos 'cosmos-mongo-account.bicep' = {
12 | name: 'cosmos-mongo-account'
13 | params: {
14 | name: accountName
15 | location: location
16 | keyVaultName: keyVaultName
17 | tags: tags
18 | connectionStringKey: connectionStringKey
19 | }
20 | }
21 |
22 | resource database 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases@2022-08-15' = {
23 | name: '${accountName}/${databaseName}'
24 | tags: tags
25 | properties: {
26 | resource: { id: databaseName }
27 | }
28 |
29 | resource list 'collections' = [for collection in collections: {
30 | name: collection.name
31 | properties: {
32 | resource: {
33 | id: collection.id
34 | shardKey: { _id: collection.shardKey }
35 | indexes: [ { key: { keys: [ collection.indexKey ] } } ]
36 | }
37 | }
38 | }]
39 |
40 | dependsOn: [
41 | cosmos
42 | ]
43 | }
44 |
45 | output connectionStringKey string = connectionStringKey
46 | output databaseName string = databaseName
47 | output endpoint string = cosmos.outputs.endpoint
48 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/sql/cosmos-sql-account.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cosmos DB for NoSQL account.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param keyVaultName string
7 |
8 | module cosmos '../../cosmos/cosmos-account.bicep' = {
9 | name: 'cosmos-account'
10 | params: {
11 | name: name
12 | location: location
13 | tags: tags
14 | keyVaultName: keyVaultName
15 | kind: 'GlobalDocumentDB'
16 | }
17 | }
18 |
19 | output connectionStringKey string = cosmos.outputs.connectionStringKey
20 | output endpoint string = cosmos.outputs.endpoint
21 | output id string = cosmos.outputs.id
22 | output name string = cosmos.outputs.name
23 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/sql/cosmos-sql-db.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Cosmos DB for NoSQL account with a database.'
2 | param accountName string
3 | param databaseName string
4 | param location string = resourceGroup().location
5 | param tags object = {}
6 |
7 | param containers array = []
8 | param keyVaultName string
9 | param principalIds array = []
10 |
11 | module cosmos 'cosmos-sql-account.bicep' = {
12 | name: 'cosmos-sql-account'
13 | params: {
14 | name: accountName
15 | location: location
16 | tags: tags
17 | keyVaultName: keyVaultName
18 | }
19 | }
20 |
21 | resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = {
22 | name: '${accountName}/${databaseName}'
23 | properties: {
24 | resource: { id: databaseName }
25 | }
26 |
27 | resource list 'containers' = [for container in containers: {
28 | name: container.name
29 | properties: {
30 | resource: {
31 | id: container.id
32 | partitionKey: { paths: [ container.partitionKey ] }
33 | }
34 | options: {}
35 | }
36 | }]
37 |
38 | dependsOn: [
39 | cosmos
40 | ]
41 | }
42 |
43 | module roleDefinition 'cosmos-sql-role-def.bicep' = {
44 | name: 'cosmos-sql-role-definition'
45 | params: {
46 | accountName: accountName
47 | }
48 | dependsOn: [
49 | cosmos
50 | database
51 | ]
52 | }
53 |
54 | // We need batchSize(1) here because sql role assignments have to be done sequentially
55 | @batchSize(1)
56 | module userRole 'cosmos-sql-role-assign.bicep' = [for principalId in principalIds: if (!empty(principalId)) {
57 | name: 'cosmos-sql-user-role-${uniqueString(principalId)}'
58 | params: {
59 | accountName: accountName
60 | roleDefinitionId: roleDefinition.outputs.id
61 | principalId: principalId
62 | }
63 | dependsOn: [
64 | cosmos
65 | database
66 | ]
67 | }]
68 |
69 | output accountId string = cosmos.outputs.id
70 | output accountName string = cosmos.outputs.name
71 | output connectionStringKey string = cosmos.outputs.connectionStringKey
72 | output databaseName string = databaseName
73 | output endpoint string = cosmos.outputs.endpoint
74 | output roleDefinitionId string = roleDefinition.outputs.id
75 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates a SQL role assignment under an Azure Cosmos DB account.'
2 | param accountName string
3 |
4 | param roleDefinitionId string
5 | param principalId string = ''
6 |
7 | resource role 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2022-05-15' = {
8 | parent: cosmos
9 | name: guid(roleDefinitionId, principalId, cosmos.id)
10 | properties: {
11 | principalId: principalId
12 | roleDefinitionId: roleDefinitionId
13 | scope: cosmos.id
14 | }
15 | }
16 |
17 | resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
18 | name: accountName
19 | }
20 |
--------------------------------------------------------------------------------
/infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates a SQL role definition under an Azure Cosmos DB account.'
2 | param accountName string
3 |
4 | resource roleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2022-08-15' = {
5 | parent: cosmos
6 | name: guid(cosmos.id, accountName, 'sql-role')
7 | properties: {
8 | assignableScopes: [
9 | cosmos.id
10 | ]
11 | permissions: [
12 | {
13 | dataActions: [
14 | 'Microsoft.DocumentDB/databaseAccounts/readMetadata'
15 | 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*'
16 | 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*'
17 | ]
18 | notDataActions: []
19 | }
20 | ]
21 | roleName: 'Reader Writer'
22 | type: 'CustomRole'
23 | }
24 | }
25 |
26 | resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
27 | name: accountName
28 | }
29 |
30 | output id string = roleDefinition.id
31 |
--------------------------------------------------------------------------------
/infra/core/database/mysql/flexibleserver.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Database for MySQL - Flexible Server.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param sku object
7 | param storage object
8 | param administratorLogin string
9 | @secure()
10 | param administratorLoginPassword string
11 | param highAvailabilityMode string = 'Disabled'
12 | param databaseNames array = []
13 | param allowAzureIPsFirewall bool = false
14 | param allowAllIPsFirewall bool = false
15 | param allowedSingleIPs array = []
16 |
17 | // MySQL version
18 | param version string
19 |
20 | resource mysqlServer 'Microsoft.DBforMySQL/flexibleServers@2023-06-30' = {
21 | location: location
22 | tags: tags
23 | name: name
24 | sku: sku
25 | properties: {
26 | version: version
27 | administratorLogin: administratorLogin
28 | administratorLoginPassword: administratorLoginPassword
29 | storage: storage
30 | highAvailability: {
31 | mode: highAvailabilityMode
32 | }
33 | }
34 |
35 | resource database 'databases' = [for name in databaseNames: {
36 | name: name
37 | }]
38 |
39 | resource firewall_all 'firewallRules' = if (allowAllIPsFirewall) {
40 | name: 'allow-all-IPs'
41 | properties: {
42 | startIpAddress: '0.0.0.0'
43 | endIpAddress: '255.255.255.255'
44 | }
45 | }
46 |
47 | resource firewall_azure 'firewallRules' = if (allowAzureIPsFirewall) {
48 | name: 'allow-all-azure-internal-IPs'
49 | properties: {
50 | startIpAddress: '0.0.0.0'
51 | endIpAddress: '0.0.0.0'
52 | }
53 | }
54 |
55 | resource firewall_single 'firewallRules' = [for ip in allowedSingleIPs: {
56 | name: 'allow-single-${replace(ip, '.', '')}'
57 | properties: {
58 | startIpAddress: ip
59 | endIpAddress: ip
60 | }
61 | }]
62 |
63 | }
64 |
65 | output MYSQL_DOMAIN_NAME string = mysqlServer.properties.fullyQualifiedDomainName
66 |
--------------------------------------------------------------------------------
/infra/core/database/postgresql/flexibleserver.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Database for PostgreSQL - Flexible Server.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param sku object
7 | param storage object
8 | param administratorLogin string
9 | @secure()
10 | param administratorLoginPassword string
11 | param databaseNames array = []
12 | param allowAzureIPsFirewall bool = false
13 | param allowAllIPsFirewall bool = false
14 | param allowedSingleIPs array = []
15 |
16 | // PostgreSQL version
17 | param version string
18 |
19 | // Latest official version 2022-12-01 does not have Bicep types available
20 | resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = {
21 | location: location
22 | tags: tags
23 | name: name
24 | sku: sku
25 | properties: {
26 | version: version
27 | administratorLogin: administratorLogin
28 | administratorLoginPassword: administratorLoginPassword
29 | storage: storage
30 | highAvailability: {
31 | mode: 'Disabled'
32 | }
33 | }
34 |
35 | resource database 'databases' = [for name in databaseNames: {
36 | name: name
37 | }]
38 |
39 | resource firewall_all 'firewallRules' = if (allowAllIPsFirewall) {
40 | name: 'allow-all-IPs'
41 | properties: {
42 | startIpAddress: '0.0.0.0'
43 | endIpAddress: '255.255.255.255'
44 | }
45 | }
46 |
47 | resource firewall_azure 'firewallRules' = if (allowAzureIPsFirewall) {
48 | name: 'allow-all-azure-internal-IPs'
49 | properties: {
50 | startIpAddress: '0.0.0.0'
51 | endIpAddress: '0.0.0.0'
52 | }
53 | }
54 |
55 | resource firewall_single 'firewallRules' = [for ip in allowedSingleIPs: {
56 | name: 'allow-single-${replace(ip, '.', '')}'
57 | properties: {
58 | startIpAddress: ip
59 | endIpAddress: ip
60 | }
61 | }]
62 |
63 | }
64 |
65 | output POSTGRES_DOMAIN_NAME string = postgresServer.properties.fullyQualifiedDomainName
66 |
--------------------------------------------------------------------------------
/infra/core/host/aks-agent-pool.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Adds an agent pool to an Azure Kubernetes Service (AKS) cluster.'
2 | param clusterName string
3 |
4 | @description('The agent pool name')
5 | param name string
6 |
7 | @description('The agent pool configuration')
8 | param config object
9 |
10 | resource aksCluster 'Microsoft.ContainerService/managedClusters@2023-10-02-preview' existing = {
11 | name: clusterName
12 | }
13 |
14 | resource nodePool 'Microsoft.ContainerService/managedClusters/agentPools@2023-10-02-preview' = {
15 | parent: aksCluster
16 | name: name
17 | properties: config
18 | }
19 |
--------------------------------------------------------------------------------
/infra/core/host/appservice-appsettings.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Updates app settings for an Azure App Service.'
2 | @description('The name of the app service resource within the current resource group scope')
3 | param name string
4 |
5 | @description('The app settings to be applied to the app service')
6 | @secure()
7 | param appSettings object
8 |
9 | resource appService 'Microsoft.Web/sites@2022-03-01' existing = {
10 | name: name
11 | }
12 |
13 | resource settings 'Microsoft.Web/sites/config@2022-03-01' = {
14 | name: 'appsettings'
15 | parent: appService
16 | properties: appSettings
17 | }
18 |
--------------------------------------------------------------------------------
/infra/core/host/appserviceplan.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure App Service plan.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param kind string = ''
7 | param reserved bool = true
8 | param sku object
9 |
10 | resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
11 | name: name
12 | location: location
13 | tags: tags
14 | sku: sku
15 | kind: kind
16 | properties: {
17 | reserved: reserved
18 | }
19 | }
20 |
21 | output id string = appServicePlan.id
22 | output name string = appServicePlan.name
23 |
--------------------------------------------------------------------------------
/infra/core/host/container-apps-environment.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Container Apps environment.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | @description('Name of the Application Insights resource')
7 | param applicationInsightsName string = ''
8 |
9 | @description('Specifies if Dapr is enabled')
10 | param daprEnabled bool = false
11 |
12 | @description('Name of the Log Analytics workspace')
13 | param logAnalyticsWorkspaceName string
14 |
15 | resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' = {
16 | name: name
17 | location: location
18 | tags: tags
19 | properties: {
20 | appLogsConfiguration: {
21 | destination: 'log-analytics'
22 | logAnalyticsConfiguration: {
23 | customerId: logAnalyticsWorkspace.properties.customerId
24 | sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
25 | }
26 | }
27 | daprAIInstrumentationKey: daprEnabled && !empty(applicationInsightsName) ? applicationInsights.properties.InstrumentationKey : ''
28 | }
29 | }
30 |
31 | resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
32 | name: logAnalyticsWorkspaceName
33 | }
34 |
35 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (daprEnabled && !empty(applicationInsightsName)) {
36 | name: applicationInsightsName
37 | }
38 |
39 | output defaultDomain string = containerAppsEnvironment.properties.defaultDomain
40 | output id string = containerAppsEnvironment.id
41 | output name string = containerAppsEnvironment.name
42 |
--------------------------------------------------------------------------------
/infra/core/host/container-apps.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Container Registry and an Azure Container Apps environment.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param containerAppsEnvironmentName string
7 | param containerRegistryName string
8 | param containerRegistryResourceGroupName string = ''
9 | param containerRegistryAdminUserEnabled bool = false
10 | param logAnalyticsWorkspaceName string
11 | param applicationInsightsName string = ''
12 |
13 | module containerAppsEnvironment 'container-apps-environment.bicep' = {
14 | name: '${name}-container-apps-environment'
15 | params: {
16 | name: containerAppsEnvironmentName
17 | location: location
18 | tags: tags
19 | logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
20 | applicationInsightsName: applicationInsightsName
21 | }
22 | }
23 |
24 | module containerRegistry 'container-registry.bicep' = {
25 | name: '${name}-container-registry'
26 | scope: !empty(containerRegistryResourceGroupName) ? resourceGroup(containerRegistryResourceGroupName) : resourceGroup()
27 | params: {
28 | name: containerRegistryName
29 | location: location
30 | adminUserEnabled: containerRegistryAdminUserEnabled
31 | tags: tags
32 | }
33 | }
34 |
35 | output defaultDomain string = containerAppsEnvironment.outputs.defaultDomain
36 | output environmentName string = containerAppsEnvironment.outputs.name
37 | output environmentId string = containerAppsEnvironment.outputs.id
38 |
39 | output registryLoginServer string = containerRegistry.outputs.loginServer
40 | output registryName string = containerRegistry.outputs.name
41 |
--------------------------------------------------------------------------------
/infra/core/host/functions.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Function in an existing Azure App Service plan.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | // Reference Properties
7 | param applicationInsightsName string = ''
8 | param appServicePlanId string
9 | param keyVaultName string = ''
10 | param managedIdentity bool = !empty(keyVaultName)
11 | param storageAccountName string
12 |
13 | // Runtime Properties
14 | @allowed([
15 | 'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom'
16 | ])
17 | param runtimeName string
18 | param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}'
19 | param runtimeVersion string
20 |
21 | // Function Settings
22 | @allowed([
23 | '~4', '~3', '~2', '~1'
24 | ])
25 | param extensionVersion string = '~4'
26 |
27 | // Microsoft.Web/sites Properties
28 | param kind string = 'functionapp,linux'
29 |
30 | // Microsoft.Web/sites/config
31 | param allowedOrigins array = []
32 | param alwaysOn bool = true
33 | param appCommandLine string = ''
34 | @secure()
35 | param appSettings object = {}
36 | param clientAffinityEnabled bool = false
37 | param enableOryxBuild bool = contains(kind, 'linux')
38 | param functionAppScaleLimit int = -1
39 | param linuxFxVersion string = runtimeNameAndVersion
40 | param minimumElasticInstanceCount int = -1
41 | param numberOfWorkers int = -1
42 | param scmDoBuildDuringDeployment bool = true
43 | param use32BitWorkerProcess bool = false
44 | param healthCheckPath string = ''
45 |
46 | module functions 'appservice.bicep' = {
47 | name: '${name}-functions'
48 | params: {
49 | name: name
50 | location: location
51 | tags: tags
52 | allowedOrigins: allowedOrigins
53 | alwaysOn: alwaysOn
54 | appCommandLine: appCommandLine
55 | applicationInsightsName: applicationInsightsName
56 | appServicePlanId: appServicePlanId
57 | appSettings: union(appSettings, {
58 | AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${storage.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
59 | FUNCTIONS_EXTENSION_VERSION: extensionVersion
60 | FUNCTIONS_WORKER_RUNTIME: runtimeName
61 | })
62 | clientAffinityEnabled: clientAffinityEnabled
63 | enableOryxBuild: enableOryxBuild
64 | functionAppScaleLimit: functionAppScaleLimit
65 | healthCheckPath: healthCheckPath
66 | keyVaultName: keyVaultName
67 | kind: kind
68 | linuxFxVersion: linuxFxVersion
69 | managedIdentity: managedIdentity
70 | minimumElasticInstanceCount: minimumElasticInstanceCount
71 | numberOfWorkers: numberOfWorkers
72 | runtimeName: runtimeName
73 | runtimeVersion: runtimeVersion
74 | runtimeNameAndVersion: runtimeNameAndVersion
75 | scmDoBuildDuringDeployment: scmDoBuildDuringDeployment
76 | use32BitWorkerProcess: use32BitWorkerProcess
77 | }
78 | }
79 |
80 | resource storage 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
81 | name: storageAccountName
82 | }
83 |
84 | output identityPrincipalId string = managedIdentity ? functions.outputs.identityPrincipalId : ''
85 | output name string = functions.outputs.name
86 | output uri string = functions.outputs.uri
87 |
--------------------------------------------------------------------------------
/infra/core/host/staticwebapp.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Static Web Apps instance.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param sku object = {
7 | name: 'Free'
8 | tier: 'Free'
9 | }
10 |
11 | resource web 'Microsoft.Web/staticSites@2022-03-01' = {
12 | name: name
13 | location: location
14 | tags: tags
15 | sku: sku
16 | properties: {
17 | provider: 'Custom'
18 | }
19 | }
20 |
21 | output name string = web.name
22 | output uri string = 'https://${web.properties.defaultHostname}'
23 |
--------------------------------------------------------------------------------
/infra/core/monitor/applicationinsights.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Application Insights instance based on an existing Log Analytics workspace.'
2 | param name string
3 | param dashboardName string = ''
4 | param location string = resourceGroup().location
5 | param tags object = {}
6 | param logAnalyticsWorkspaceId string
7 |
8 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
9 | name: name
10 | location: location
11 | tags: tags
12 | kind: 'web'
13 | properties: {
14 | Application_Type: 'web'
15 | WorkspaceResourceId: logAnalyticsWorkspaceId
16 | }
17 | }
18 |
19 | module applicationInsightsDashboard 'applicationinsights-dashboard.bicep' = if (!empty(dashboardName)) {
20 | name: 'application-insights-dashboard'
21 | params: {
22 | name: dashboardName
23 | location: location
24 | applicationInsightsName: applicationInsights.name
25 | }
26 | }
27 |
28 | output connectionString string = applicationInsights.properties.ConnectionString
29 | output id string = applicationInsights.id
30 | output instrumentationKey string = applicationInsights.properties.InstrumentationKey
31 | output name string = applicationInsights.name
32 |
--------------------------------------------------------------------------------
/infra/core/monitor/loganalytics.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates a Log Analytics workspace.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
7 | name: name
8 | location: location
9 | tags: tags
10 | properties: any({
11 | retentionInDays: 30
12 | features: {
13 | searchVersion: 1
14 | }
15 | sku: {
16 | name: 'PerGB2018'
17 | }
18 | })
19 | }
20 |
21 | output id string = logAnalytics.id
22 | output name string = logAnalytics.name
23 |
--------------------------------------------------------------------------------
/infra/core/monitor/monitoring.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Application Insights instance and a Log Analytics workspace.'
2 | param logAnalyticsName string
3 | param applicationInsightsName string
4 | param applicationInsightsDashboardName string = ''
5 | param location string = resourceGroup().location
6 | param tags object = {}
7 |
8 | module logAnalytics 'loganalytics.bicep' = {
9 | name: 'loganalytics'
10 | params: {
11 | name: logAnalyticsName
12 | location: location
13 | tags: tags
14 | }
15 | }
16 |
17 | module applicationInsights 'applicationinsights.bicep' = {
18 | name: 'applicationinsights'
19 | params: {
20 | name: applicationInsightsName
21 | location: location
22 | tags: tags
23 | dashboardName: applicationInsightsDashboardName
24 | logAnalyticsWorkspaceId: logAnalytics.outputs.id
25 | }
26 | }
27 |
28 | output applicationInsightsConnectionString string = applicationInsights.outputs.connectionString
29 | output applicationInsightsId string = applicationInsights.outputs.id
30 | output applicationInsightsInstrumentationKey string = applicationInsights.outputs.instrumentationKey
31 | output applicationInsightsName string = applicationInsights.outputs.name
32 | output logAnalyticsWorkspaceId string = logAnalytics.outputs.id
33 | output logAnalyticsWorkspaceName string = logAnalytics.outputs.name
34 |
--------------------------------------------------------------------------------
/infra/core/networking/cdn-endpoint.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Adds an endpoint to an Azure CDN profile.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | @description('The name of the CDN profile resource')
7 | @minLength(1)
8 | param cdnProfileName string
9 |
10 | @description('Delivery policy rules')
11 | param deliveryPolicyRules array = []
12 |
13 | @description('The origin URL for the endpoint')
14 | @minLength(1)
15 | param originUrl string
16 |
17 | resource endpoint 'Microsoft.Cdn/profiles/endpoints@2022-05-01-preview' = {
18 | parent: cdnProfile
19 | name: name
20 | location: location
21 | tags: tags
22 | properties: {
23 | originHostHeader: originUrl
24 | isHttpAllowed: false
25 | isHttpsAllowed: true
26 | queryStringCachingBehavior: 'UseQueryString'
27 | optimizationType: 'GeneralWebDelivery'
28 | origins: [
29 | {
30 | name: replace(originUrl, '.', '-')
31 | properties: {
32 | hostName: originUrl
33 | originHostHeader: originUrl
34 | priority: 1
35 | weight: 1000
36 | enabled: true
37 | }
38 | }
39 | ]
40 | deliveryPolicy: {
41 | rules: deliveryPolicyRules
42 | }
43 | }
44 | }
45 |
46 | resource cdnProfile 'Microsoft.Cdn/profiles@2022-05-01-preview' existing = {
47 | name: cdnProfileName
48 | }
49 |
50 | output id string = endpoint.id
51 | output name string = endpoint.name
52 | output uri string = 'https://${endpoint.properties.hostName}'
53 |
--------------------------------------------------------------------------------
/infra/core/networking/cdn-profile.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure CDN profile.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | @description('The pricing tier of this CDN profile')
7 | @allowed([
8 | 'Custom_Verizon'
9 | 'Premium_AzureFrontDoor'
10 | 'Premium_Verizon'
11 | 'StandardPlus_955BandWidth_ChinaCdn'
12 | 'StandardPlus_AvgBandWidth_ChinaCdn'
13 | 'StandardPlus_ChinaCdn'
14 | 'Standard_955BandWidth_ChinaCdn'
15 | 'Standard_Akamai'
16 | 'Standard_AvgBandWidth_ChinaCdn'
17 | 'Standard_AzureFrontDoor'
18 | 'Standard_ChinaCdn'
19 | 'Standard_Microsoft'
20 | 'Standard_Verizon'
21 | ])
22 | param sku string = 'Standard_Microsoft'
23 |
24 | resource profile 'Microsoft.Cdn/profiles@2022-05-01-preview' = {
25 | name: name
26 | location: location
27 | tags: tags
28 | sku: {
29 | name: sku
30 | }
31 | }
32 |
33 | output id string = profile.id
34 | output name string = profile.name
35 |
--------------------------------------------------------------------------------
/infra/core/networking/cdn.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure CDN profile with a single endpoint.'
2 | param location string = resourceGroup().location
3 | param tags object = {}
4 |
5 | @description('Name of the CDN endpoint resource')
6 | param cdnEndpointName string
7 |
8 | @description('Name of the CDN profile resource')
9 | param cdnProfileName string
10 |
11 | @description('Delivery policy rules')
12 | param deliveryPolicyRules array = []
13 |
14 | @description('Origin URL for the CDN endpoint')
15 | param originUrl string
16 |
17 | module cdnProfile 'cdn-profile.bicep' = {
18 | name: 'cdn-profile'
19 | params: {
20 | name: cdnProfileName
21 | location: location
22 | tags: tags
23 | }
24 | }
25 |
26 | module cdnEndpoint 'cdn-endpoint.bicep' = {
27 | name: 'cdn-endpoint'
28 | params: {
29 | name: cdnEndpointName
30 | location: location
31 | tags: tags
32 | cdnProfileName: cdnProfile.outputs.name
33 | originUrl: originUrl
34 | deliveryPolicyRules: deliveryPolicyRules
35 | }
36 | }
37 |
38 | output endpointName string = cdnEndpoint.outputs.name
39 | output endpointId string = cdnEndpoint.outputs.id
40 | output profileName string = cdnProfile.outputs.name
41 | output profileId string = cdnProfile.outputs.id
42 | output uri string = cdnEndpoint.outputs.uri
43 |
--------------------------------------------------------------------------------
/infra/core/search/search-services.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure AI Search instance.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param sku object = {
7 | name: 'standard'
8 | }
9 |
10 | param authOptions object = {}
11 | param disableLocalAuth bool = false
12 | param disabledDataExfiltrationOptions array = []
13 | param encryptionWithCmk object = {
14 | enforcement: 'Unspecified'
15 | }
16 | @allowed([
17 | 'default'
18 | 'highDensity'
19 | ])
20 | param hostingMode string = 'default'
21 | param networkRuleSet object = {
22 | bypass: 'None'
23 | ipRules: []
24 | }
25 | param partitionCount int = 1
26 | @allowed([
27 | 'enabled'
28 | 'disabled'
29 | ])
30 | param publicNetworkAccess string = 'enabled'
31 | param replicaCount int = 1
32 | @allowed([
33 | 'disabled'
34 | 'free'
35 | 'standard'
36 | ])
37 | param semanticSearch string = 'disabled'
38 |
39 | var searchIdentityProvider = (sku.name == 'free') ? null : {
40 | type: 'SystemAssigned'
41 | }
42 |
43 | resource search 'Microsoft.Search/searchServices@2021-04-01-preview' = {
44 | name: name
45 | location: location
46 | tags: tags
47 | // The free tier does not support managed identity
48 | identity: searchIdentityProvider
49 | properties: {
50 | authOptions: authOptions
51 | disableLocalAuth: disableLocalAuth
52 | disabledDataExfiltrationOptions: disabledDataExfiltrationOptions
53 | encryptionWithCmk: encryptionWithCmk
54 | hostingMode: hostingMode
55 | networkRuleSet: networkRuleSet
56 | partitionCount: partitionCount
57 | publicNetworkAccess: publicNetworkAccess
58 | replicaCount: replicaCount
59 | semanticSearch: semanticSearch
60 | }
61 | sku: sku
62 | }
63 |
64 | output id string = search.id
65 | output endpoint string = 'https://${name}.search.windows.net/'
66 | output name string = search.name
67 | output principalId string = !empty(searchIdentityProvider) ? search.identity.principalId : ''
68 |
69 |
--------------------------------------------------------------------------------
/infra/core/security/aks-managed-cluster-access.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Assigns RBAC role to the specified AKS cluster and principal.'
2 | param clusterName string
3 | param principalId string
4 |
5 | var aksClusterAdminRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b')
6 |
7 | resource aksRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
8 | scope: aksCluster // Use when specifying a scope that is different than the deployment scope
9 | name: guid(subscription().id, resourceGroup().id, principalId, aksClusterAdminRole)
10 | properties: {
11 | roleDefinitionId: aksClusterAdminRole
12 | principalType: 'User'
13 | principalId: principalId
14 | }
15 | }
16 |
17 | resource aksCluster 'Microsoft.ContainerService/managedClusters@2023-10-02-preview' existing = {
18 | name: clusterName
19 | }
20 |
--------------------------------------------------------------------------------
/infra/core/security/configstore-access.bicep:
--------------------------------------------------------------------------------
1 | @description('Name of Azure App Configuration store')
2 | param configStoreName string
3 |
4 | @description('The principal ID of the service principal to assign the role to')
5 | param principalId string
6 |
7 | resource configStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = {
8 | name: configStoreName
9 | }
10 |
11 | var configStoreDataReaderRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')
12 |
13 | resource configStoreDataReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
14 | name: guid(subscription().id, resourceGroup().id, principalId, configStoreDataReaderRole)
15 | scope: configStore
16 | properties: {
17 | roleDefinitionId: configStoreDataReaderRole
18 | principalId: principalId
19 | principalType: 'ServicePrincipal'
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/infra/core/security/keyvault-access.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Assigns an Azure Key Vault access policy.'
2 | param name string = 'add'
3 |
4 | param keyVaultName string
5 | param permissions object = { secrets: [ 'get', 'list' ] }
6 | param principalId string
7 |
8 | resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
9 | parent: keyVault
10 | name: name
11 | properties: {
12 | accessPolicies: [ {
13 | objectId: principalId
14 | tenantId: subscription().tenantId
15 | permissions: permissions
16 | } ]
17 | }
18 | }
19 |
20 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
21 | name: keyVaultName
22 | }
23 |
--------------------------------------------------------------------------------
/infra/core/security/keyvault-secret.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates or updates a secret in an Azure Key Vault.'
2 | param name string
3 | param tags object = {}
4 | param keyVaultName string
5 | param contentType string = 'string'
6 | @description('The value of the secret. Provide only derived values like blob storage access, but do not hard code any secrets in your templates')
7 | @secure()
8 | param secretValue string
9 |
10 | param enabled bool = true
11 | param exp int = 0
12 | param nbf int = 0
13 |
14 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
15 | name: name
16 | tags: tags
17 | parent: keyVault
18 | properties: {
19 | attributes: {
20 | enabled: enabled
21 | exp: exp
22 | nbf: nbf
23 | }
24 | contentType: contentType
25 | value: secretValue
26 | }
27 | }
28 |
29 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
30 | name: keyVaultName
31 | }
32 |
--------------------------------------------------------------------------------
/infra/core/security/keyvault.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure Key Vault.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | param principalId string = ''
7 |
8 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
9 | name: name
10 | location: location
11 | tags: tags
12 | properties: {
13 | tenantId: subscription().tenantId
14 | sku: { family: 'A', name: 'standard' }
15 | accessPolicies: !empty(principalId) ? [
16 | {
17 | objectId: principalId
18 | permissions: { secrets: [ 'get', 'list' ] }
19 | tenantId: subscription().tenantId
20 | }
21 | ] : []
22 | }
23 | }
24 |
25 | output endpoint string = keyVault.properties.vaultUri
26 | output id string = keyVault.id
27 | output name string = keyVault.name
28 |
--------------------------------------------------------------------------------
/infra/core/security/registry-access.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Assigns ACR Pull permissions to access an Azure Container Registry.'
2 | param containerRegistryName string
3 | param principalId string
4 |
5 | var acrPullRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
6 |
7 | resource aksAcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
8 | scope: containerRegistry // Use when specifying a scope that is different than the deployment scope
9 | name: guid(subscription().id, resourceGroup().id, principalId, acrPullRole)
10 | properties: {
11 | roleDefinitionId: acrPullRole
12 | principalType: 'ServicePrincipal'
13 | principalId: principalId
14 | }
15 | }
16 |
17 | resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = {
18 | name: containerRegistryName
19 | }
20 |
--------------------------------------------------------------------------------
/infra/core/security/role.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates a role assignment for a service principal.'
2 | param principalId string
3 |
4 | @allowed([
5 | 'Device'
6 | 'ForeignGroup'
7 | 'Group'
8 | 'ServicePrincipal'
9 | 'User'
10 | ])
11 | param principalType string = 'ServicePrincipal'
12 | param roleDefinitionId string
13 |
14 | resource role 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
15 | name: guid(subscription().id, resourceGroup().id, principalId, roleDefinitionId)
16 | properties: {
17 | principalId: principalId
18 | principalType: principalType
19 | roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/infra/core/storage/storage-account.bicep:
--------------------------------------------------------------------------------
1 | metadata description = 'Creates an Azure storage account.'
2 | param name string
3 | param location string = resourceGroup().location
4 | param tags object = {}
5 |
6 | @allowed([
7 | 'Cool'
8 | 'Hot'
9 | 'Premium' ])
10 | param accessTier string = 'Hot'
11 | param allowBlobPublicAccess bool = true
12 | param allowCrossTenantReplication bool = true
13 | param allowSharedKeyAccess bool = true
14 | param containers array = []
15 | param corsRules array = []
16 | param defaultToOAuthAuthentication bool = false
17 | param deleteRetentionPolicy object = {}
18 | @allowed([ 'AzureDnsZone', 'Standard' ])
19 | param dnsEndpointType string = 'Standard'
20 | param files array = []
21 | param kind string = 'StorageV2'
22 | param minimumTlsVersion string = 'TLS1_2'
23 | param queues array = []
24 | param shareDeleteRetentionPolicy object = {}
25 | param supportsHttpsTrafficOnly bool = true
26 | param tables array = []
27 | param networkAcls object = {
28 | bypass: 'AzureServices'
29 | defaultAction: 'Allow'
30 | }
31 | @allowed([ 'Enabled', 'Disabled' ])
32 | param publicNetworkAccess string = 'Enabled'
33 | param sku object = { name: 'Standard_LRS' }
34 |
35 | resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
36 | name: name
37 | location: location
38 | tags: tags
39 | kind: kind
40 | sku: sku
41 | properties: {
42 | accessTier: accessTier
43 | allowBlobPublicAccess: allowBlobPublicAccess
44 | allowCrossTenantReplication: allowCrossTenantReplication
45 | allowSharedKeyAccess: allowSharedKeyAccess
46 | defaultToOAuthAuthentication: defaultToOAuthAuthentication
47 | dnsEndpointType: dnsEndpointType
48 | minimumTlsVersion: minimumTlsVersion
49 | networkAcls: networkAcls
50 | publicNetworkAccess: publicNetworkAccess
51 | supportsHttpsTrafficOnly: supportsHttpsTrafficOnly
52 | }
53 |
54 | resource blobServices 'blobServices' = if (!empty(containers)) {
55 | name: 'default'
56 | properties: {
57 | cors: {
58 | corsRules: corsRules
59 | }
60 | deleteRetentionPolicy: deleteRetentionPolicy
61 | }
62 | resource container 'containers' = [for container in containers: {
63 | name: container.name
64 | properties: {
65 | publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None'
66 | }
67 | }]
68 | }
69 |
70 | resource fileServices 'fileServices' = if (!empty(files)) {
71 | name: 'default'
72 | properties: {
73 | cors: {
74 | corsRules: corsRules
75 | }
76 | shareDeleteRetentionPolicy: shareDeleteRetentionPolicy
77 | }
78 | }
79 |
80 | resource queueServices 'queueServices' = if (!empty(queues)) {
81 | name: 'default'
82 | properties: {
83 |
84 | }
85 | resource queue 'queues' = [for queue in queues: {
86 | name: queue.name
87 | properties: {
88 | metadata: {}
89 | }
90 | }]
91 | }
92 |
93 | resource tableServices 'tableServices' = if (!empty(tables)) {
94 | name: 'default'
95 | properties: {}
96 | }
97 | }
98 |
99 | output id string = storage.id
100 | output name string = storage.name
101 | output primaryEndpoints object = storage.properties.primaryEndpoints
102 |
--------------------------------------------------------------------------------
/infra/core/testing/loadtesting.bicep:
--------------------------------------------------------------------------------
1 | param name string
2 | param location string = resourceGroup().location
3 | param managedIdentity bool = false
4 | param tags object = {}
5 |
6 | resource loadTest 'Microsoft.LoadTestService/loadTests@2022-12-01' = {
7 | name: name
8 | location: location
9 | tags: tags
10 | identity: { type: managedIdentity ? 'SystemAssigned' : 'None' }
11 | properties: {
12 | }
13 | }
14 |
15 | output loadTestingName string = loadTest.name
16 |
--------------------------------------------------------------------------------
/infra/main.parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "environmentName": {
6 | "value": "${AZURE_ENV_NAME}"
7 | },
8 | "location": {
9 | "value": "${AZURE_LOCATION}"
10 | },
11 | "principalId": {
12 | "value": "${AZURE_PRINCIPAL_ID}"
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@sap-cloud-sdk/util": "^3.25.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/sample-http-requests/business-partner-requests.http:
--------------------------------------------------------------------------------
1 | GET http://localhost:8080/health HTTP/1.1
2 | content-type: application/json
3 |
4 | ###
5 |
6 | GET http://localhost:8080/business-partner HTTP/1.1
7 | content-type: application/json
8 | x-ms-token-aad-access-token: your-access-token-if-any
9 |
10 | ###
11 |
12 | GET http://localhost:8080/business-partner/1003764 HTTP/1.1
13 | content-type: application/json
14 |
15 | ###
16 |
17 | PUT http://localhost:8080/business-partner/1003764/address/28238 HTTP/1.1
18 | content-type: application/json
19 |
20 | {
21 | "houseNumber": "1"
22 | }
23 |
24 | ###
25 |
26 | DELETE http://localhost:8080/business-partner/1003764/address/28238 HTTP/1.1
27 | content-type: application/json
28 |
29 | ###
30 |
31 | POST http://localhost:8080/business-partner/1003764/address HTTP/1.1
32 | content-type: application/json
33 |
34 | {
35 | "businessPartner": "1003764",
36 | "cityName": "Bangalore",
37 | "country": "IN",
38 | "houseNumber": "",
39 | "postalCode": "560066",
40 | "streetName": "123",
41 | "toAddressUsage":
42 | [
43 | {
44 | "addressUsage": "XXDEFAULT",
45 | "standardUsage": true
46 | }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/src/api/.deployment:
--------------------------------------------------------------------------------
1 | [config]
2 | SCM_DO_BUILD_DURING_DEPLOYMENT=true
--------------------------------------------------------------------------------
/src/api/manifest.yaml:
--------------------------------------------------------------------------------
1 | applications:
2 | - name: cloudsdkapp
3 | path: .
4 | buildpacks:
5 | - nodejs_buildpack
6 | memory: 1G
7 | command: npm run start:prod
8 | random-route: true
9 | build-parameters:
10 | builder: custom
11 | commands:
12 | - npm run build
--------------------------------------------------------------------------------
/src/api/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src"
5 | }
6 |
--------------------------------------------------------------------------------
/src/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sap-cloud-sdk-on-azure",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "start": "nest start",
12 | "start:dev": "nest start --watch",
13 | "start:debug": "nest start --debug --watch",
14 | "start:prod": "node dist/src/main.js",
15 | "lint-check": "rome check .",
16 | "lint": "rome check --apply-suggested .",
17 | "format": "rome format --write .",
18 | "test": "jest",
19 | "test:watch": "jest --watch",
20 | "test:cov": "jest --coverage",
21 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
22 | "test:e2e": "jest --config ./test/jest-e2e.json"
23 | },
24 | "dependencies": {
25 | "@nestjs/common": "^9.3.9",
26 | "@nestjs/config": "^2.3.1",
27 | "@nestjs/core": "^10.3.7",
28 | "@nestjs/platform-express": "^10.3.7",
29 | "@sap-cloud-sdk/http-client": "^3.0.1",
30 | "@sap-cloud-sdk/odata-v2": "^3.0.1",
31 | "pug": "^3.0.3",
32 | "reflect-metadata": "^0.1.13",
33 | "rimraf": "^4.3.1",
34 | "rxjs": "^7.8.0"
35 | },
36 | "devDependencies": {
37 | "@nestjs/cli": "^10.4.5",
38 | "@nestjs/schematics": "^9.0.4",
39 | "@nestjs/testing": "^10.3.7",
40 | "@sap-cloud-sdk/generator": "^3.0.1",
41 | "@types/express": "^4.17.17",
42 | "@types/jest": "29.4.0",
43 | "@types/node": "^18.14.6",
44 | "@types/supertest": "^2.0.12",
45 | "jest": "29.5.0",
46 | "prettier": "^2.8.4",
47 | "rome": "^11.0.0",
48 | "source-map-support": "^0.5.21",
49 | "supertest": "^6.3.3",
50 | "ts-jest": "29.0.5",
51 | "ts-loader": "^9.4.2",
52 | "ts-node": "^10.9.1",
53 | "tsconfig-paths": "4.1.2",
54 | "typescript": "^4.9.5"
55 | },
56 | "jest": {
57 | "moduleFileExtensions": [
58 | "js",
59 | "json",
60 | "ts"
61 | ],
62 | "rootDir": "./src",
63 | "testRegex": ".*\\.spec\\.ts$",
64 | "transform": {
65 | "^.+\\.(t|j)s$": "ts-jest"
66 | },
67 | "collectCoverageFrom": [
68 | "**/*.(t|j)s"
69 | ],
70 | "coverageDirectory": "../coverage",
71 | "testEnvironment": "node"
72 | },
73 | "ts-standard": {
74 | "ignore": [
75 | "dist",
76 | "service-specifications",
77 | "services/business-partner-service-1"
78 | ]
79 | }
80 | }
--------------------------------------------------------------------------------
/src/api/rome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/rome/configuration_schema.json",
3 | "files": {
4 | "ignore": [
5 | "./dist/*",
6 | "./node_modules/*",
7 | "./services/*"
8 | ]
9 | },
10 | "linter": {
11 | "enabled": true,
12 | "rules": {
13 | "recommended": true
14 | }
15 | },
16 | "formatter": {
17 | "enabled": true,
18 | "formatWithErrors": false,
19 | "indentStyle": "tab",
20 | "indentSize": 2,
21 | "lineWidth": 80,
22 | "ignore": []
23 | }
24 | }
--------------------------------------------------------------------------------
/src/api/service-specifications/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "service-specifications/ZAPI_BUSINESS_PARTNER.edmx": {
3 | "packageName": "business-partner-service-1",
4 | "directoryName": "business-partner-service-1",
5 | "basePath": "/sap/opu/odata/sap/API_BUSINESS_PARTNER"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/AddressEmailAddress.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { AddressEmailAddressApi } from './AddressEmailAddressApi';
13 |
14 | /**
15 | * This class represents the entity "A_AddressEmailAddress" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class AddressEmailAddress
18 | extends Entity
19 | implements AddressEmailAddressType
20 | {
21 | /**
22 | * Technical entity name for AddressEmailAddress.
23 | */
24 | static _entityName = 'A_AddressEmailAddress';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the AddressEmailAddress entity
31 | */
32 | static _keys = ['AddressID', 'Person', 'OrdinalNumber'];
33 | /**
34 | * Address Number.
35 | * Maximum length: 10.
36 | */
37 | addressId!: DeserializedType;
38 | /**
39 | * Person Number.
40 | * Maximum length: 10.
41 | */
42 | person!: DeserializedType;
43 | /**
44 | * Sequence Number.
45 | * Maximum length: 3.
46 | */
47 | ordinalNumber!: DeserializedType;
48 | /**
49 | * Flag: this address is the default address.
50 | * @nullable
51 | */
52 | isDefaultEmailAddress?: DeserializedType | null;
53 | /**
54 | * E-Mail Address.
55 | * Maximum length: 241.
56 | * @nullable
57 | */
58 | emailAddress?: DeserializedType | null;
59 | /**
60 | * E-Mail Address Search Field.
61 | * Maximum length: 20.
62 | * @nullable
63 | */
64 | searchEmailAddress?: DeserializedType | null;
65 | /**
66 | * Communication link notes.
67 | * Maximum length: 50.
68 | * @nullable
69 | */
70 | addressCommunicationRemarkText?: DeserializedType | null;
71 |
72 | constructor(readonly _entityApi: AddressEmailAddressApi) {
73 | super(_entityApi);
74 | }
75 | }
76 |
77 | export interface AddressEmailAddressType<
78 | T extends DeSerializers = DefaultDeSerializers
79 | > {
80 | addressId: DeserializedType;
81 | person: DeserializedType;
82 | ordinalNumber: DeserializedType;
83 | isDefaultEmailAddress?: DeserializedType | null;
84 | emailAddress?: DeserializedType | null;
85 | searchEmailAddress?: DeserializedType | null;
86 | addressCommunicationRemarkText?: DeserializedType | null;
87 | }
88 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/AddressFaxNumber.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { AddressFaxNumberApi } from './AddressFaxNumberApi';
13 |
14 | /**
15 | * This class represents the entity "A_AddressFaxNumber" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class AddressFaxNumber
18 | extends Entity
19 | implements AddressFaxNumberType
20 | {
21 | /**
22 | * Technical entity name for AddressFaxNumber.
23 | */
24 | static _entityName = 'A_AddressFaxNumber';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the AddressFaxNumber entity
31 | */
32 | static _keys = ['AddressID', 'Person', 'OrdinalNumber'];
33 | /**
34 | * Address Number.
35 | * Maximum length: 10.
36 | */
37 | addressId!: DeserializedType;
38 | /**
39 | * Person Number.
40 | * Maximum length: 10.
41 | */
42 | person!: DeserializedType;
43 | /**
44 | * Sequence Number.
45 | * Maximum length: 3.
46 | */
47 | ordinalNumber!: DeserializedType;
48 | /**
49 | * Standard Sender Address in this Communication Type.
50 | * @nullable
51 | */
52 | isDefaultFaxNumber?: DeserializedType | null;
53 | /**
54 | * Country/Region for Telephone/Fax Number.
55 | * Maximum length: 3.
56 | * @nullable
57 | */
58 | faxCountry?: DeserializedType | null;
59 | /**
60 | * Fax number: dialling code+number.
61 | * Maximum length: 30.
62 | * @nullable
63 | */
64 | faxNumber?: DeserializedType | null;
65 | /**
66 | * Fax no.: Extension.
67 | * Maximum length: 10.
68 | * @nullable
69 | */
70 | faxNumberExtension?: DeserializedType | null;
71 | /**
72 | * Complete number: dialling code+number+extension.
73 | * Maximum length: 30.
74 | * @nullable
75 | */
76 | internationalFaxNumber?: DeserializedType | null;
77 | /**
78 | * Communication link notes.
79 | * Maximum length: 50.
80 | * @nullable
81 | */
82 | addressCommunicationRemarkText?: DeserializedType | null;
83 |
84 | constructor(readonly _entityApi: AddressFaxNumberApi) {
85 | super(_entityApi);
86 | }
87 | }
88 |
89 | export interface AddressFaxNumberType<
90 | T extends DeSerializers = DefaultDeSerializers
91 | > {
92 | addressId: DeserializedType;
93 | person: DeserializedType;
94 | ordinalNumber: DeserializedType;
95 | isDefaultFaxNumber?: DeserializedType | null;
96 | faxCountry?: DeserializedType | null;
97 | faxNumber?: DeserializedType | null;
98 | faxNumberExtension?: DeserializedType | null;
99 | internationalFaxNumber?: DeserializedType | null;
100 | addressCommunicationRemarkText?: DeserializedType | null;
101 | }
102 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/AddressHomePageUrl.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { AddressHomePageUrlApi } from './AddressHomePageUrlApi';
13 |
14 | /**
15 | * This class represents the entity "A_AddressHomePageURL" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class AddressHomePageUrl
18 | extends Entity
19 | implements AddressHomePageUrlType
20 | {
21 | /**
22 | * Technical entity name for AddressHomePageUrl.
23 | */
24 | static _entityName = 'A_AddressHomePageURL';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the AddressHomePageUrl entity
31 | */
32 | static _keys = [
33 | 'AddressID',
34 | 'Person',
35 | 'OrdinalNumber',
36 | 'ValidityStartDate',
37 | 'IsDefaultURLAddress'
38 | ];
39 | /**
40 | * Address Number.
41 | * Maximum length: 10.
42 | */
43 | addressId!: DeserializedType;
44 | /**
45 | * Person Number.
46 | * Maximum length: 10.
47 | */
48 | person!: DeserializedType;
49 | /**
50 | * Sequence Number.
51 | * Maximum length: 3.
52 | */
53 | ordinalNumber!: DeserializedType;
54 | /**
55 | * Valid-from date - in current Release only 00010101 possible.
56 | */
57 | validityStartDate!: DeserializedType;
58 | /**
59 | * Flag: this address is the default address.
60 | */
61 | isDefaultUrlAddress!: DeserializedType;
62 | /**
63 | * URI address search field.
64 | * Maximum length: 50.
65 | * @nullable
66 | */
67 | searchUrlAddress?: DeserializedType | null;
68 | /**
69 | * Communication link notes.
70 | * Maximum length: 50.
71 | * @nullable
72 | */
73 | addressCommunicationRemarkText?: DeserializedType | null;
74 | /**
75 | * URI field length.
76 | * @nullable
77 | */
78 | urlFieldLength?: DeserializedType | null;
79 | /**
80 | * Universal Resource Identifier (URI).
81 | * Maximum length: 2048.
82 | * @nullable
83 | */
84 | websiteUrl?: DeserializedType | null;
85 |
86 | constructor(readonly _entityApi: AddressHomePageUrlApi) {
87 | super(_entityApi);
88 | }
89 | }
90 |
91 | export interface AddressHomePageUrlType<
92 | T extends DeSerializers = DefaultDeSerializers
93 | > {
94 | addressId: DeserializedType;
95 | person: DeserializedType;
96 | ordinalNumber: DeserializedType;
97 | validityStartDate: DeserializedType;
98 | isDefaultUrlAddress: DeserializedType;
99 | searchUrlAddress?: DeserializedType | null;
100 | addressCommunicationRemarkText?: DeserializedType | null;
101 | urlFieldLength?: DeserializedType | null;
102 | websiteUrl?: DeserializedType | null;
103 | }
104 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BpContactToAddressRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import { Moment } from 'moment';
7 | import {
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | GetAllRequestBuilder,
11 | GetByKeyRequestBuilder,
12 | DeserializedType,
13 | RequestBuilder
14 | } from '@sap-cloud-sdk/odata-v2';
15 | import { BpContactToAddress } from './BpContactToAddress';
16 |
17 | /**
18 | * Request builder class for operations supported on the {@link BpContactToAddress} entity.
19 | */
20 | export class BpContactToAddressRequestBuilder<
21 | T extends DeSerializers = DefaultDeSerializers
22 | > extends RequestBuilder, T> {
23 | /**
24 | * Returns a request builder for retrieving one `BpContactToAddress` entity based on its keys.
25 | * @param relationshipNumber Key property. See {@link BpContactToAddress.relationshipNumber}.
26 | * @param businessPartnerCompany Key property. See {@link BpContactToAddress.businessPartnerCompany}.
27 | * @param businessPartnerPerson Key property. See {@link BpContactToAddress.businessPartnerPerson}.
28 | * @param validityEndDate Key property. See {@link BpContactToAddress.validityEndDate}.
29 | * @param addressId Key property. See {@link BpContactToAddress.addressId}.
30 | * @returns A request builder for creating requests to retrieve one `BpContactToAddress` entity based on its keys.
31 | */
32 | getByKey(
33 | relationshipNumber: DeserializedType,
34 | businessPartnerCompany: DeserializedType,
35 | businessPartnerPerson: DeserializedType,
36 | validityEndDate: DeserializedType,
37 | addressId: DeserializedType
38 | ): GetByKeyRequestBuilder, T> {
39 | return new GetByKeyRequestBuilder, T>(
40 | this.entityApi,
41 | {
42 | RelationshipNumber: relationshipNumber,
43 | BusinessPartnerCompany: businessPartnerCompany,
44 | BusinessPartnerPerson: businessPartnerPerson,
45 | ValidityEndDate: validityEndDate,
46 | AddressID: addressId
47 | }
48 | );
49 | }
50 |
51 | /**
52 | * Returns a request builder for querying all `BpContactToAddress` entities.
53 | * @returns A request builder for creating requests to retrieve all `BpContactToAddress` entities.
54 | */
55 | getAll(): GetAllRequestBuilder, T> {
56 | return new GetAllRequestBuilder, T>(this.entityApi);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BpContactToFuncAndDeptRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import { Moment } from 'moment';
7 | import {
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | GetAllRequestBuilder,
11 | GetByKeyRequestBuilder,
12 | UpdateRequestBuilder,
13 | DeserializedType,
14 | RequestBuilder
15 | } from '@sap-cloud-sdk/odata-v2';
16 | import { BpContactToFuncAndDept } from './BpContactToFuncAndDept';
17 |
18 | /**
19 | * Request builder class for operations supported on the {@link BpContactToFuncAndDept} entity.
20 | */
21 | export class BpContactToFuncAndDeptRequestBuilder<
22 | T extends DeSerializers = DefaultDeSerializers
23 | > extends RequestBuilder, T> {
24 | /**
25 | * Returns a request builder for retrieving one `BpContactToFuncAndDept` entity based on its keys.
26 | * @param relationshipNumber Key property. See {@link BpContactToFuncAndDept.relationshipNumber}.
27 | * @param businessPartnerCompany Key property. See {@link BpContactToFuncAndDept.businessPartnerCompany}.
28 | * @param businessPartnerPerson Key property. See {@link BpContactToFuncAndDept.businessPartnerPerson}.
29 | * @param validityEndDate Key property. See {@link BpContactToFuncAndDept.validityEndDate}.
30 | * @returns A request builder for creating requests to retrieve one `BpContactToFuncAndDept` entity based on its keys.
31 | */
32 | getByKey(
33 | relationshipNumber: DeserializedType,
34 | businessPartnerCompany: DeserializedType,
35 | businessPartnerPerson: DeserializedType,
36 | validityEndDate: DeserializedType
37 | ): GetByKeyRequestBuilder, T> {
38 | return new GetByKeyRequestBuilder, T>(
39 | this.entityApi,
40 | {
41 | RelationshipNumber: relationshipNumber,
42 | BusinessPartnerCompany: businessPartnerCompany,
43 | BusinessPartnerPerson: businessPartnerPerson,
44 | ValidityEndDate: validityEndDate
45 | }
46 | );
47 | }
48 |
49 | /**
50 | * Returns a request builder for querying all `BpContactToFuncAndDept` entities.
51 | * @returns A request builder for creating requests to retrieve all `BpContactToFuncAndDept` entities.
52 | */
53 | getAll(): GetAllRequestBuilder, T> {
54 | return new GetAllRequestBuilder, T>(
55 | this.entityApi
56 | );
57 | }
58 |
59 | /**
60 | * Returns a request builder for updating an entity of type `BpContactToFuncAndDept`.
61 | * @param entity The entity to be updated
62 | * @returns A request builder for creating requests that update an entity of type `BpContactToFuncAndDept`.
63 | */
64 | update(
65 | entity: BpContactToFuncAndDept
66 | ): UpdateRequestBuilder, T> {
67 | return new UpdateRequestBuilder, T>(
68 | this.entityApi,
69 | entity
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BuPaAddressUsage.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { BuPaAddressUsageApi } from './BuPaAddressUsageApi';
13 |
14 | /**
15 | * This class represents the entity "A_BuPaAddressUsage" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class BuPaAddressUsage
18 | extends Entity
19 | implements BuPaAddressUsageType
20 | {
21 | /**
22 | * Technical entity name for BuPaAddressUsage.
23 | */
24 | static _entityName = 'A_BuPaAddressUsage';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the BuPaAddressUsage entity
31 | */
32 | static _keys = [
33 | 'BusinessPartner',
34 | 'ValidityEndDate',
35 | 'AddressUsage',
36 | 'AddressID'
37 | ];
38 | /**
39 | * Business Partner Number.
40 | * Maximum length: 10.
41 | */
42 | businessPartner!: DeserializedType;
43 | /**
44 | * Validity End of a Business Partner Address Usage.
45 | */
46 | validityEndDate!: DeserializedType;
47 | /**
48 | * Address Type.
49 | * Maximum length: 10.
50 | */
51 | addressUsage!: DeserializedType;
52 | /**
53 | * Address Number.
54 | * Maximum length: 10.
55 | */
56 | addressId!: DeserializedType;
57 | /**
58 | * Validity Start of a Business Partner Address Usage.
59 | * @nullable
60 | */
61 | validityStartDate?: DeserializedType | null;
62 | /**
63 | * Indicator: Standard Address Usage.
64 | * @nullable
65 | */
66 | standardUsage?: DeserializedType | null;
67 | /**
68 | * Authorization Group.
69 | * Maximum length: 4.
70 | * @nullable
71 | */
72 | authorizationGroup?: DeserializedType | null;
73 |
74 | constructor(readonly _entityApi: BuPaAddressUsageApi) {
75 | super(_entityApi);
76 | }
77 | }
78 |
79 | export interface BuPaAddressUsageType<
80 | T extends DeSerializers = DefaultDeSerializers
81 | > {
82 | businessPartner: DeserializedType;
83 | validityEndDate: DeserializedType;
84 | addressUsage: DeserializedType;
85 | addressId: DeserializedType;
86 | validityStartDate?: DeserializedType | null;
87 | standardUsage?: DeserializedType | null;
88 | authorizationGroup?: DeserializedType | null;
89 | }
90 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BuPaIndustry.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { BuPaIndustryApi } from './BuPaIndustryApi';
13 |
14 | /**
15 | * This class represents the entity "A_BuPaIndustry" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class BuPaIndustry
18 | extends Entity
19 | implements BuPaIndustryType
20 | {
21 | /**
22 | * Technical entity name for BuPaIndustry.
23 | */
24 | static _entityName = 'A_BuPaIndustry';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the BuPaIndustry entity
31 | */
32 | static _keys = ['IndustrySector', 'IndustrySystemType', 'BusinessPartner'];
33 | /**
34 | * Industry.
35 | * Maximum length: 10.
36 | */
37 | industrySector!: DeserializedType;
38 | /**
39 | * Industry System.
40 | * Maximum length: 4.
41 | */
42 | industrySystemType!: DeserializedType;
43 | /**
44 | * Business Partner Number.
45 | * Maximum length: 10.
46 | */
47 | businessPartner!: DeserializedType;
48 | /**
49 | * Industry is Standard for BP in Industry System.
50 | * Maximum length: 1.
51 | * @nullable
52 | */
53 | isStandardIndustry?: DeserializedType | null;
54 | /**
55 | * Description.
56 | * Maximum length: 100.
57 | * @nullable
58 | */
59 | industryKeyDescription?: DeserializedType | null;
60 |
61 | constructor(readonly _entityApi: BuPaIndustryApi) {
62 | super(_entityApi);
63 | }
64 | }
65 |
66 | export interface BuPaIndustryType<
67 | T extends DeSerializers = DefaultDeSerializers
68 | > {
69 | industrySector: DeserializedType;
70 | industrySystemType: DeserializedType;
71 | businessPartner: DeserializedType;
72 | isStandardIndustry?: DeserializedType | null;
73 | industryKeyDescription?: DeserializedType | null;
74 | }
75 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BusinessPartnerRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | DefaultDeSerializers,
8 | DeSerializers,
9 | GetAllRequestBuilder,
10 | GetByKeyRequestBuilder,
11 | CreateRequestBuilder,
12 | UpdateRequestBuilder,
13 | DeserializedType,
14 | RequestBuilder
15 | } from '@sap-cloud-sdk/odata-v2';
16 | import { BusinessPartner } from './BusinessPartner';
17 |
18 | /**
19 | * Request builder class for operations supported on the {@link BusinessPartner} entity.
20 | */
21 | export class BusinessPartnerRequestBuilder<
22 | T extends DeSerializers = DefaultDeSerializers
23 | > extends RequestBuilder, T> {
24 | /**
25 | * Returns a request builder for retrieving one `BusinessPartner` entity based on its keys.
26 | * @param businessPartner Key property. See {@link BusinessPartner.businessPartner}.
27 | * @returns A request builder for creating requests to retrieve one `BusinessPartner` entity based on its keys.
28 | */
29 | getByKey(
30 | businessPartner: DeserializedType
31 | ): GetByKeyRequestBuilder, T> {
32 | return new GetByKeyRequestBuilder, T>(this.entityApi, {
33 | BusinessPartner: businessPartner
34 | });
35 | }
36 |
37 | /**
38 | * Returns a request builder for querying all `BusinessPartner` entities.
39 | * @returns A request builder for creating requests to retrieve all `BusinessPartner` entities.
40 | */
41 | getAll(): GetAllRequestBuilder, T> {
42 | return new GetAllRequestBuilder, T>(this.entityApi);
43 | }
44 |
45 | /**
46 | * Returns a request builder for creating a `BusinessPartner` entity.
47 | * @param entity The entity to be created
48 | * @returns A request builder for creating requests that create an entity of type `BusinessPartner`.
49 | */
50 | create(
51 | entity: BusinessPartner
52 | ): CreateRequestBuilder, T> {
53 | return new CreateRequestBuilder, T>(
54 | this.entityApi,
55 | entity
56 | );
57 | }
58 |
59 | /**
60 | * Returns a request builder for updating an entity of type `BusinessPartner`.
61 | * @param entity The entity to be updated
62 | * @returns A request builder for creating requests that update an entity of type `BusinessPartner`.
63 | */
64 | update(
65 | entity: BusinessPartner
66 | ): UpdateRequestBuilder, T> {
67 | return new UpdateRequestBuilder, T>(
68 | this.entityApi,
69 | entity
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BusinessPartnerRole.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { BusinessPartnerRoleApi } from './BusinessPartnerRoleApi';
13 |
14 | /**
15 | * This class represents the entity "A_BusinessPartnerRole" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class BusinessPartnerRole
18 | extends Entity
19 | implements BusinessPartnerRoleType
20 | {
21 | /**
22 | * Technical entity name for BusinessPartnerRole.
23 | */
24 | static _entityName = 'A_BusinessPartnerRole';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the BusinessPartnerRole entity
31 | */
32 | static _keys = ['BusinessPartner', 'BusinessPartnerRole'];
33 | /**
34 | * Business Partner Number.
35 | * Maximum length: 10.
36 | */
37 | businessPartner!: DeserializedType;
38 | /**
39 | * BP Role.
40 | * Maximum length: 6.
41 | */
42 | businessPartnerRole!: DeserializedType;
43 | /**
44 | * Validity Start of a BP Role.
45 | * @nullable
46 | */
47 | validFrom?: DeserializedType | null;
48 | /**
49 | * Validity End of a BP Role.
50 | * @nullable
51 | */
52 | validTo?: DeserializedType | null;
53 | /**
54 | * Authorization Group.
55 | * Maximum length: 4.
56 | * @nullable
57 | */
58 | authorizationGroup?: DeserializedType | null;
59 |
60 | constructor(readonly _entityApi: BusinessPartnerRoleApi) {
61 | super(_entityApi);
62 | }
63 | }
64 |
65 | export interface BusinessPartnerRoleType<
66 | T extends DeSerializers = DefaultDeSerializers
67 | > {
68 | businessPartner: DeserializedType;
69 | businessPartnerRole: DeserializedType;
70 | validFrom?: DeserializedType | null;
71 | validTo?: DeserializedType | null;
72 | authorizationGroup?: DeserializedType | null;
73 | }
74 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BusinessPartnerRoleRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | DefaultDeSerializers,
8 | DeSerializers,
9 | GetAllRequestBuilder,
10 | GetByKeyRequestBuilder,
11 | CreateRequestBuilder,
12 | UpdateRequestBuilder,
13 | DeserializedType,
14 | RequestBuilder
15 | } from '@sap-cloud-sdk/odata-v2';
16 | import { BusinessPartnerRole } from './BusinessPartnerRole';
17 |
18 | /**
19 | * Request builder class for operations supported on the {@link BusinessPartnerRole} entity.
20 | */
21 | export class BusinessPartnerRoleRequestBuilder<
22 | T extends DeSerializers = DefaultDeSerializers
23 | > extends RequestBuilder, T> {
24 | /**
25 | * Returns a request builder for retrieving one `BusinessPartnerRole` entity based on its keys.
26 | * @param businessPartner Key property. See {@link BusinessPartnerRole.businessPartner}.
27 | * @param businessPartnerRole Key property. See {@link BusinessPartnerRole.businessPartnerRole}.
28 | * @returns A request builder for creating requests to retrieve one `BusinessPartnerRole` entity based on its keys.
29 | */
30 | getByKey(
31 | businessPartner: DeserializedType,
32 | businessPartnerRole: DeserializedType
33 | ): GetByKeyRequestBuilder, T> {
34 | return new GetByKeyRequestBuilder, T>(
35 | this.entityApi,
36 | {
37 | BusinessPartner: businessPartner,
38 | BusinessPartnerRole: businessPartnerRole
39 | }
40 | );
41 | }
42 |
43 | /**
44 | * Returns a request builder for querying all `BusinessPartnerRole` entities.
45 | * @returns A request builder for creating requests to retrieve all `BusinessPartnerRole` entities.
46 | */
47 | getAll(): GetAllRequestBuilder, T> {
48 | return new GetAllRequestBuilder, T>(this.entityApi);
49 | }
50 |
51 | /**
52 | * Returns a request builder for creating a `BusinessPartnerRole` entity.
53 | * @param entity The entity to be created
54 | * @returns A request builder for creating requests that create an entity of type `BusinessPartnerRole`.
55 | */
56 | create(
57 | entity: BusinessPartnerRole
58 | ): CreateRequestBuilder, T> {
59 | return new CreateRequestBuilder, T>(
60 | this.entityApi,
61 | entity
62 | );
63 | }
64 |
65 | /**
66 | * Returns a request builder for updating an entity of type `BusinessPartnerRole`.
67 | * @param entity The entity to be updated
68 | * @returns A request builder for creating requests that update an entity of type `BusinessPartnerRole`.
69 | */
70 | update(
71 | entity: BusinessPartnerRole
72 | ): UpdateRequestBuilder, T> {
73 | return new UpdateRequestBuilder, T>(
74 | this.entityApi,
75 | entity
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/BusinessPartnerTaxNumber.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { BusinessPartnerTaxNumberApi } from './BusinessPartnerTaxNumberApi';
13 |
14 | /**
15 | * This class represents the entity "A_BusinessPartnerTaxNumber" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class BusinessPartnerTaxNumber<
18 | T extends DeSerializers = DefaultDeSerializers
19 | >
20 | extends Entity
21 | implements BusinessPartnerTaxNumberType
22 | {
23 | /**
24 | * Technical entity name for BusinessPartnerTaxNumber.
25 | */
26 | static _entityName = 'A_BusinessPartnerTaxNumber';
27 | /**
28 | * Default url path for the according service.
29 | */
30 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
31 | /**
32 | * All key fields of the BusinessPartnerTaxNumber entity
33 | */
34 | static _keys = ['BusinessPartner', 'BPTaxType'];
35 | /**
36 | * Business Partner Number.
37 | * Maximum length: 10.
38 | */
39 | businessPartner!: DeserializedType;
40 | /**
41 | * Tax Number Category.
42 | * Maximum length: 4.
43 | */
44 | bpTaxType!: DeserializedType;
45 | /**
46 | * Business Partner Tax Number.
47 | * Maximum length: 20.
48 | * @nullable
49 | */
50 | bpTaxNumber?: DeserializedType | null;
51 | /**
52 | * Business Partner Tax Number.
53 | * Maximum length: 60.
54 | * @nullable
55 | */
56 | bpTaxLongNumber?: DeserializedType | null;
57 | /**
58 | * Authorization Group.
59 | * Maximum length: 4.
60 | * @nullable
61 | */
62 | authorizationGroup?: DeserializedType | null;
63 |
64 | constructor(readonly _entityApi: BusinessPartnerTaxNumberApi) {
65 | super(_entityApi);
66 | }
67 | }
68 |
69 | export interface BusinessPartnerTaxNumberType<
70 | T extends DeSerializers = DefaultDeSerializers
71 | > {
72 | businessPartner: DeserializedType;
73 | bpTaxType: DeserializedType;
74 | bpTaxNumber?: DeserializedType | null;
75 | bpTaxLongNumber?: DeserializedType | null;
76 | authorizationGroup?: DeserializedType | null;
77 | }
78 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerCompanyRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | DefaultDeSerializers,
8 | DeSerializers,
9 | GetAllRequestBuilder,
10 | GetByKeyRequestBuilder,
11 | CreateRequestBuilder,
12 | UpdateRequestBuilder,
13 | DeserializedType,
14 | RequestBuilder
15 | } from '@sap-cloud-sdk/odata-v2';
16 | import { CustomerCompany } from './CustomerCompany';
17 |
18 | /**
19 | * Request builder class for operations supported on the {@link CustomerCompany} entity.
20 | */
21 | export class CustomerCompanyRequestBuilder<
22 | T extends DeSerializers = DefaultDeSerializers
23 | > extends RequestBuilder, T> {
24 | /**
25 | * Returns a request builder for retrieving one `CustomerCompany` entity based on its keys.
26 | * @param customer Key property. See {@link CustomerCompany.customer}.
27 | * @param companyCode Key property. See {@link CustomerCompany.companyCode}.
28 | * @returns A request builder for creating requests to retrieve one `CustomerCompany` entity based on its keys.
29 | */
30 | getByKey(
31 | customer: DeserializedType,
32 | companyCode: DeserializedType
33 | ): GetByKeyRequestBuilder, T> {
34 | return new GetByKeyRequestBuilder, T>(this.entityApi, {
35 | Customer: customer,
36 | CompanyCode: companyCode
37 | });
38 | }
39 |
40 | /**
41 | * Returns a request builder for querying all `CustomerCompany` entities.
42 | * @returns A request builder for creating requests to retrieve all `CustomerCompany` entities.
43 | */
44 | getAll(): GetAllRequestBuilder, T> {
45 | return new GetAllRequestBuilder, T>(this.entityApi);
46 | }
47 |
48 | /**
49 | * Returns a request builder for creating a `CustomerCompany` entity.
50 | * @param entity The entity to be created
51 | * @returns A request builder for creating requests that create an entity of type `CustomerCompany`.
52 | */
53 | create(
54 | entity: CustomerCompany
55 | ): CreateRequestBuilder, T> {
56 | return new CreateRequestBuilder, T>(
57 | this.entityApi,
58 | entity
59 | );
60 | }
61 |
62 | /**
63 | * Returns a request builder for updating an entity of type `CustomerCompany`.
64 | * @param entity The entity to be updated
65 | * @returns A request builder for creating requests that update an entity of type `CustomerCompany`.
66 | */
67 | update(
68 | entity: CustomerCompany
69 | ): UpdateRequestBuilder, T> {
70 | return new UpdateRequestBuilder, T>(
71 | this.entityApi,
72 | entity
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerCompanyText.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { CustomerCompanyTextApi } from './CustomerCompanyTextApi';
13 |
14 | /**
15 | * This class represents the entity "A_CustomerCompanyText" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class CustomerCompanyText
18 | extends Entity
19 | implements CustomerCompanyTextType
20 | {
21 | /**
22 | * Technical entity name for CustomerCompanyText.
23 | */
24 | static _entityName = 'A_CustomerCompanyText';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the CustomerCompanyText entity
31 | */
32 | static _keys = ['Customer', 'CompanyCode', 'Language', 'LongTextID'];
33 | /**
34 | * Customer Number.
35 | * Maximum length: 10.
36 | */
37 | customer!: DeserializedType;
38 | /**
39 | * Company Code.
40 | * Maximum length: 4.
41 | */
42 | companyCode!: DeserializedType;
43 | /**
44 | * Language key.
45 | * Maximum length: 2.
46 | */
47 | language!: DeserializedType;
48 | /**
49 | * Text ID.
50 | * Maximum length: 4.
51 | */
52 | longTextId!: DeserializedType;
53 | /**
54 | * String.
55 | * @nullable
56 | */
57 | longText?: DeserializedType | null;
58 |
59 | constructor(readonly _entityApi: CustomerCompanyTextApi) {
60 | super(_entityApi);
61 | }
62 | }
63 |
64 | export interface CustomerCompanyTextType<
65 | T extends DeSerializers = DefaultDeSerializers
66 | > {
67 | customer: DeserializedType;
68 | companyCode: DeserializedType;
69 | language: DeserializedType;
70 | longTextId: DeserializedType;
71 | longText?: DeserializedType | null;
72 | }
73 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | DefaultDeSerializers,
8 | DeSerializers,
9 | GetAllRequestBuilder,
10 | GetByKeyRequestBuilder,
11 | UpdateRequestBuilder,
12 | DeserializedType,
13 | RequestBuilder
14 | } from '@sap-cloud-sdk/odata-v2';
15 | import { Customer } from './Customer';
16 |
17 | /**
18 | * Request builder class for operations supported on the {@link Customer} entity.
19 | */
20 | export class CustomerRequestBuilder<
21 | T extends DeSerializers = DefaultDeSerializers
22 | > extends RequestBuilder, T> {
23 | /**
24 | * Returns a request builder for retrieving one `Customer` entity based on its keys.
25 | * @param customer Key property. See {@link Customer.customer}.
26 | * @returns A request builder for creating requests to retrieve one `Customer` entity based on its keys.
27 | */
28 | getByKey(
29 | customer: DeserializedType
30 | ): GetByKeyRequestBuilder, T> {
31 | return new GetByKeyRequestBuilder, T>(this.entityApi, {
32 | Customer: customer
33 | });
34 | }
35 |
36 | /**
37 | * Returns a request builder for querying all `Customer` entities.
38 | * @returns A request builder for creating requests to retrieve all `Customer` entities.
39 | */
40 | getAll(): GetAllRequestBuilder, T> {
41 | return new GetAllRequestBuilder, T>(this.entityApi);
42 | }
43 |
44 | /**
45 | * Returns a request builder for updating an entity of type `Customer`.
46 | * @param entity The entity to be updated
47 | * @returns A request builder for creating requests that update an entity of type `Customer`.
48 | */
49 | update(entity: Customer): UpdateRequestBuilder, T> {
50 | return new UpdateRequestBuilder, T>(this.entityApi, entity);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerSalesAreaRequestBuilder.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | DefaultDeSerializers,
8 | DeSerializers,
9 | GetAllRequestBuilder,
10 | GetByKeyRequestBuilder,
11 | CreateRequestBuilder,
12 | UpdateRequestBuilder,
13 | DeserializedType,
14 | RequestBuilder
15 | } from '@sap-cloud-sdk/odata-v2';
16 | import { CustomerSalesArea } from './CustomerSalesArea';
17 |
18 | /**
19 | * Request builder class for operations supported on the {@link CustomerSalesArea} entity.
20 | */
21 | export class CustomerSalesAreaRequestBuilder<
22 | T extends DeSerializers = DefaultDeSerializers
23 | > extends RequestBuilder, T> {
24 | /**
25 | * Returns a request builder for retrieving one `CustomerSalesArea` entity based on its keys.
26 | * @param customer Key property. See {@link CustomerSalesArea.customer}.
27 | * @param salesOrganization Key property. See {@link CustomerSalesArea.salesOrganization}.
28 | * @param distributionChannel Key property. See {@link CustomerSalesArea.distributionChannel}.
29 | * @param division Key property. See {@link CustomerSalesArea.division}.
30 | * @returns A request builder for creating requests to retrieve one `CustomerSalesArea` entity based on its keys.
31 | */
32 | getByKey(
33 | customer: DeserializedType,
34 | salesOrganization: DeserializedType,
35 | distributionChannel: DeserializedType,
36 | division: DeserializedType
37 | ): GetByKeyRequestBuilder, T> {
38 | return new GetByKeyRequestBuilder, T>(this.entityApi, {
39 | Customer: customer,
40 | SalesOrganization: salesOrganization,
41 | DistributionChannel: distributionChannel,
42 | Division: division
43 | });
44 | }
45 |
46 | /**
47 | * Returns a request builder for querying all `CustomerSalesArea` entities.
48 | * @returns A request builder for creating requests to retrieve all `CustomerSalesArea` entities.
49 | */
50 | getAll(): GetAllRequestBuilder, T> {
51 | return new GetAllRequestBuilder, T>(this.entityApi);
52 | }
53 |
54 | /**
55 | * Returns a request builder for creating a `CustomerSalesArea` entity.
56 | * @param entity The entity to be created
57 | * @returns A request builder for creating requests that create an entity of type `CustomerSalesArea`.
58 | */
59 | create(
60 | entity: CustomerSalesArea
61 | ): CreateRequestBuilder, T> {
62 | return new CreateRequestBuilder, T>(
63 | this.entityApi,
64 | entity
65 | );
66 | }
67 |
68 | /**
69 | * Returns a request builder for updating an entity of type `CustomerSalesArea`.
70 | * @param entity The entity to be updated
71 | * @returns A request builder for creating requests that update an entity of type `CustomerSalesArea`.
72 | */
73 | update(
74 | entity: CustomerSalesArea
75 | ): UpdateRequestBuilder, T> {
76 | return new UpdateRequestBuilder, T>(
77 | this.entityApi,
78 | entity
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerSalesAreaTax.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { CustomerSalesAreaTaxApi } from './CustomerSalesAreaTaxApi';
13 |
14 | /**
15 | * This class represents the entity "A_CustomerSalesAreaTax" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class CustomerSalesAreaTax<
18 | T extends DeSerializers = DefaultDeSerializers
19 | >
20 | extends Entity
21 | implements CustomerSalesAreaTaxType
22 | {
23 | /**
24 | * Technical entity name for CustomerSalesAreaTax.
25 | */
26 | static _entityName = 'A_CustomerSalesAreaTax';
27 | /**
28 | * Default url path for the according service.
29 | */
30 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
31 | /**
32 | * All key fields of the CustomerSalesAreaTax entity
33 | */
34 | static _keys = [
35 | 'Customer',
36 | 'SalesOrganization',
37 | 'DistributionChannel',
38 | 'Division',
39 | 'DepartureCountry',
40 | 'CustomerTaxCategory'
41 | ];
42 | /**
43 | * Customer Number.
44 | * Maximum length: 10.
45 | */
46 | customer!: DeserializedType;
47 | /**
48 | * Sales Organization.
49 | * Maximum length: 4.
50 | */
51 | salesOrganization!: DeserializedType;
52 | /**
53 | * Reference distrib.channel for cust.and material masters.
54 | * Maximum length: 2.
55 | */
56 | distributionChannel!: DeserializedType;
57 | /**
58 | * Division.
59 | * Maximum length: 2.
60 | */
61 | division!: DeserializedType;
62 | /**
63 | * Departure Country/Region (from which the goods are sent).
64 | * Maximum length: 3.
65 | */
66 | departureCountry!: DeserializedType;
67 | /**
68 | * Tax category (sales tax, federal sales tax,...).
69 | * Maximum length: 4.
70 | */
71 | customerTaxCategory!: DeserializedType;
72 | /**
73 | * Tax classification for customer.
74 | * Maximum length: 1.
75 | * @nullable
76 | */
77 | customerTaxClassification?: DeserializedType | null;
78 |
79 | constructor(readonly _entityApi: CustomerSalesAreaTaxApi) {
80 | super(_entityApi);
81 | }
82 | }
83 |
84 | export interface CustomerSalesAreaTaxType<
85 | T extends DeSerializers = DefaultDeSerializers
86 | > {
87 | customer: DeserializedType;
88 | salesOrganization: DeserializedType;
89 | distributionChannel: DeserializedType;
90 | division: DeserializedType;
91 | departureCountry: DeserializedType;
92 | customerTaxCategory: DeserializedType;
93 | customerTaxClassification?: DeserializedType | null;
94 | }
95 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerSalesAreaText.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { CustomerSalesAreaTextApi } from './CustomerSalesAreaTextApi';
13 |
14 | /**
15 | * This class represents the entity "A_CustomerSalesAreaText" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class CustomerSalesAreaText<
18 | T extends DeSerializers = DefaultDeSerializers
19 | >
20 | extends Entity
21 | implements CustomerSalesAreaTextType
22 | {
23 | /**
24 | * Technical entity name for CustomerSalesAreaText.
25 | */
26 | static _entityName = 'A_CustomerSalesAreaText';
27 | /**
28 | * Default url path for the according service.
29 | */
30 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
31 | /**
32 | * All key fields of the CustomerSalesAreaText entity
33 | */
34 | static _keys = [
35 | 'Customer',
36 | 'SalesOrganization',
37 | 'DistributionChannel',
38 | 'Division',
39 | 'Language',
40 | 'LongTextID'
41 | ];
42 | /**
43 | * Customer Number.
44 | * Maximum length: 10.
45 | */
46 | customer!: DeserializedType;
47 | /**
48 | * Sales Organization.
49 | * Maximum length: 4.
50 | */
51 | salesOrganization!: DeserializedType;
52 | /**
53 | * Distribution Channel.
54 | * Maximum length: 2.
55 | */
56 | distributionChannel!: DeserializedType;
57 | /**
58 | * Division.
59 | * Maximum length: 2.
60 | */
61 | division!: DeserializedType;
62 | /**
63 | * Language key.
64 | * Maximum length: 2.
65 | */
66 | language!: DeserializedType;
67 | /**
68 | * Text ID.
69 | * Maximum length: 4.
70 | */
71 | longTextId!: DeserializedType;
72 | /**
73 | * String.
74 | * @nullable
75 | */
76 | longText?: DeserializedType | null;
77 |
78 | constructor(readonly _entityApi: CustomerSalesAreaTextApi) {
79 | super(_entityApi);
80 | }
81 | }
82 |
83 | export interface CustomerSalesAreaTextType<
84 | T extends DeSerializers = DefaultDeSerializers
85 | > {
86 | customer: DeserializedType;
87 | salesOrganization: DeserializedType;
88 | distributionChannel: DeserializedType;
89 | division: DeserializedType;
90 | language: DeserializedType;
91 | longTextId: DeserializedType;
92 | longText?: DeserializedType | null;
93 | }
94 |
--------------------------------------------------------------------------------
/src/api/services/business-partner-service-1/CustomerTaxGrouping.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 SAP SE or an SAP affiliate company. All rights reserved.
3 | *
4 | * This is a generated file powered by the SAP Cloud SDK for JavaScript.
5 | */
6 | import {
7 | Entity,
8 | DefaultDeSerializers,
9 | DeSerializers,
10 | DeserializedType
11 | } from '@sap-cloud-sdk/odata-v2';
12 | import type { CustomerTaxGroupingApi } from './CustomerTaxGroupingApi';
13 |
14 | /**
15 | * This class represents the entity "A_CustomerTaxGrouping" of service "API_BUSINESS_PARTNER".
16 | */
17 | export class CustomerTaxGrouping
18 | extends Entity
19 | implements CustomerTaxGroupingType
20 | {
21 | /**
22 | * Technical entity name for CustomerTaxGrouping.
23 | */
24 | static _entityName = 'A_CustomerTaxGrouping';
25 | /**
26 | * Default url path for the according service.
27 | */
28 | static _defaultBasePath = '/sap/opu/odata/sap/API_BUSINESS_PARTNER';
29 | /**
30 | * All key fields of the CustomerTaxGrouping entity
31 | */
32 | static _keys = ['Customer', 'CustomerTaxGroupingCode'];
33 | /**
34 | * Customer Number.
35 | * Maximum length: 10.
36 | */
37 | customer!: DeserializedType;
38 | /**
39 | * Category Indicator for Tax Codes.
40 | * Maximum length: 3.
41 | */
42 | customerTaxGroupingCode!: DeserializedType;
43 | /**
44 | * Number of exemption certificate.
45 | * Maximum length: 15.
46 | * @nullable
47 | */
48 | custTaxGrpExemptionCertificate?: DeserializedType | null;
49 | /**
50 | * Exemption rate.
51 | * @nullable
52 | */
53 | custTaxGroupExemptionRate?: DeserializedType | null;
54 | /**
55 | * Start date of exemption.
56 | * @nullable
57 | */
58 | custTaxGroupExemptionStartDate?: DeserializedType | null;
59 | /**
60 | * End date of exemption.
61 | * @nullable
62 | */
63 | custTaxGroupExemptionEndDate?: DeserializedType | null;
64 | /**
65 | * Subjected from.
66 | * @nullable
67 | */
68 | custTaxGroupSubjectedStartDate?: DeserializedType | null;
69 | /**
70 | * Subjected until.
71 | * @nullable
72 | */
73 | custTaxGroupSubjectedEndDate?: DeserializedType | null;
74 |
75 | constructor(readonly _entityApi: CustomerTaxGroupingApi) {
76 | super(_entityApi);
77 | }
78 | }
79 |
80 | export interface CustomerTaxGroupingType<
81 | T extends DeSerializers = DefaultDeSerializers
82 | > {
83 | customer: DeserializedType