diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 4d37d8318d04..93aec0b3b0e6 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -218,6 +218,9 @@ dependencies: '@rush-temp/arm-containerservicefleet': specifier: file:./projects/arm-containerservicefleet.tgz version: file:projects/arm-containerservicefleet.tgz + '@rush-temp/arm-contoso': + specifier: file:./projects/arm-contoso.tgz + version: file:projects/arm-contoso.tgz '@rush-temp/arm-cosmosdb': specifier: file:./projects/arm-cosmosdb.tgz version: file:projects/arm-cosmosdb.tgz @@ -3916,7 +3919,7 @@ packages: /@types/bunyan@1.8.9: resolution: {integrity: sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/chai-as-promised@7.1.8: @@ -3956,7 +3959,7 @@ packages: /@types/cors@2.8.17: resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/debug@4.1.12: @@ -4031,7 +4034,7 @@ packages: /@types/is-buffer@2.0.2: resolution: {integrity: sha512-G6OXy83Va+xEo8XgqAJYOuvOMxeey9xM5XKkvwJNmN8rVdcB+r15HvHsG86hl86JvU0y1aa7Z2ERkNFYWw9ySg==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/json-schema@7.0.15: @@ -4041,19 +4044,19 @@ packages: /@types/jsonfile@6.1.4: resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/jsonwebtoken@9.0.7: resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/jws@3.2.10: resolution: {integrity: sha512-cOevhttJmssERB88/+XvZXvsq5m9JLKZNUiGfgjUb5lcPRdV2ZQciU6dU76D/qXXFYpSqkP3PrSg4hMTiafTZw==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/linkify-it@5.0.0: @@ -4106,7 +4109,7 @@ packages: /@types/mysql@2.15.26: resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/node-fetch@2.6.11: @@ -4157,7 +4160,7 @@ packages: /@types/pg@8.6.1: resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 pg-protocol: 1.7.0 pg-types: 2.2.0 dev: false @@ -4184,7 +4187,7 @@ packages: /@types/readdir-glob@1.1.5: resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/resolve@1.20.2: @@ -4235,13 +4238,13 @@ packages: /@types/stoppable@1.1.3: resolution: {integrity: sha512-7wGKIBJGE4ZxFjk9NkjAxZMLlIXroETqP1FJCdoSvKmEznwmBxQFmTB1dsCkAvVcNemuSZM5qkkd9HE/NL2JTw==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/through@0.0.33: resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/tough-cookie@4.0.5: @@ -4275,7 +4278,7 @@ packages: /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false /@types/ws@8.5.12: @@ -4298,7 +4301,7 @@ packages: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 18.19.57 + '@types/node': 22.7.7 dev: false optional: true @@ -4598,6 +4601,39 @@ packages: vitest: 1.6.0(@types/node@18.19.57)(@vitest/browser@1.6.0) dev: false + /@vitest/browser@2.1.3(playwright@1.48.1)(typescript@5.5.4)(vitest@2.1.3): + resolution: {integrity: sha512-PQ2kLLc9q8ukJutuuYsynHSr31E78/dtYEvPy4jCHLht1LmITqXTVTqu7THWdZ1kXNGrWwtdMqtt3z2mvSKdIg==} + peerDependencies: + playwright: '*' + safaridriver: '*' + vitest: 2.1.3 + webdriverio: '*' + peerDependenciesMeta: + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@testing-library/dom': 10.4.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/mocker': 2.1.3(msw@2.4.12) + '@vitest/utils': 2.1.3 + magic-string: 0.30.12 + msw: 2.4.12(typescript@5.5.4) + playwright: 1.48.1 + sirv: 2.0.4 + tinyrainbow: 1.2.0 + vitest: 2.1.3(@types/node@18.19.57)(@vitest/browser@2.1.3) + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - vite + dev: false + /@vitest/browser@2.1.3(playwright@1.48.1)(typescript@5.6.3)(vitest@2.1.3): resolution: {integrity: sha512-PQ2kLLc9q8ukJutuuYsynHSr31E78/dtYEvPy4jCHLht1LmITqXTVTqu7THWdZ1kXNGrWwtdMqtt3z2mvSKdIg==} peerDependencies: @@ -6072,7 +6108,7 @@ packages: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 18.19.57 + '@types/node': 22.7.7 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -8635,6 +8671,37 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false + /msw@2.4.12(typescript@5.5.4): + resolution: {integrity: sha512-upQMKZt0fYIB0Gj6gKc5i/PK4JrICTu3ItfXiju3FTdgQLaqARv7+jugPCsOkrWpTzzjo5iLW+4F6L/mGNukbA==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@bundled-es-modules/cookie': 2.0.0 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 3.2.0 + '@mswjs/interceptors': 0.36.5 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.5 + chalk: 4.1.2 + graphql: 16.9.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + strict-event-emitter: 0.5.1 + type-fest: 4.26.1 + typescript: 5.5.4 + yargs: 17.7.2 + dev: false + /msw@2.4.12(typescript@5.6.3): resolution: {integrity: sha512-upQMKZt0fYIB0Gj6gKc5i/PK4JrICTu3ItfXiju3FTdgQLaqARv7+jugPCsOkrWpTzzjo5iLW+4F6L/mGNukbA==} engines: {node: '>=18'} @@ -10930,6 +10997,12 @@ packages: hasBin: true dev: false + /typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + dev: false + /typescript@5.6.3: resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} @@ -14127,8 +14200,48 @@ packages: - supports-color dev: false + file:projects/arm-contoso.tgz: + resolution: {integrity: sha512-+IfbzE3xMNtIVrTsIbtYVZre38Yj0pqKNXVfpQvU11q9LBCgWMvwq/6m3Q8fEHye8NJm/6CucYgT8vgcg+cRwg==, tarball: file:projects/arm-contoso.tgz} + name: '@rush-temp/arm-contoso' + version: 0.0.0 + dependencies: + '@microsoft/api-extractor': 7.47.11(@types/node@18.19.57) + '@types/node': 18.19.57 + '@vitest/browser': 2.1.3(playwright@1.48.1)(typescript@5.5.4)(vitest@2.1.3) + '@vitest/coverage-istanbul': 2.1.3(vitest@2.1.3) + dotenv: 16.4.5 + eslint: 8.57.1 + mkdirp: 3.0.1 + playwright: 1.48.1 + prettier: 3.3.3 + rimraf: 5.0.10 + tshy: 1.18.0 + tslib: 2.8.0 + typescript: 5.5.4 + vitest: 2.1.3(@types/node@18.19.57)(@vitest/browser@2.1.3) + transitivePeerDependencies: + - '@edge-runtime/vm' + - '@vitest/ui' + - bufferutil + - happy-dom + - jsdom + - less + - lightningcss + - msw + - safaridriver + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - utf-8-validate + - vite + - webdriverio + dev: false + file:projects/arm-cosmosdb.tgz: - resolution: {integrity: sha512-2v6rqNsp3P65qn1zTQugNY4WpyjrpSlNV4fJiakvfiwyCdgDP7roXWbcXGfrp3KDJXH0soobfEehPV8zfDfWJw==, tarball: file:projects/arm-cosmosdb.tgz} + resolution: {integrity: sha512-isHxEpq7bScszTE3o6ML/F7FgseAxz0jzQ3QvL06v/O+x7cW+0eSKoIxnFy0qGk4DvUqGJylr2FtoVBmAKGmvA==, tarball: file:projects/arm-cosmosdb.tgz} name: '@rush-temp/arm-cosmosdb' version: 0.0.0 dependencies: @@ -15147,7 +15260,7 @@ packages: dev: false file:projects/arm-elasticsan.tgz: - resolution: {integrity: sha512-dy6sMLYtkbQs07JJoBu5N5PkTJ7i0fVLW3Gdl894VJaww9EFAYc9pCrMLhsOSBLvmfzgwpyAY2L1DGg7h5Yi4Q==, tarball: file:projects/arm-elasticsan.tgz} + resolution: {integrity: sha512-5/gwmooleUnum1LJ7BaIOssENX8rSEtb6cy1TK3nh1CCzNlXIH+G5QF16/KPT4+OH6+WdAwLjrATGxX/caI6gg==, tarball: file:projects/arm-elasticsan.tgz} name: '@rush-temp/arm-elasticsan' version: 0.0.0 dependencies: @@ -15295,7 +15408,7 @@ packages: dev: false file:projects/arm-fabric.tgz: - resolution: {integrity: sha512-fsC4YDGpwTkL2mW+m3h1FKq4LnKMTIJcdcznTRbca/Qv53WZvkng75BBWLXy/oTbT6yz7zIk7m4MtaxL9vgc1Q==, tarball: file:projects/arm-fabric.tgz} + resolution: {integrity: sha512-DWfFgqHfgTiuH3NNu60qsQbVvXs1fKragfniZrJLTdbpqS+qbT6vpDjhYG/kuLN/FmX8ls89FAUd6T+etr8Hpg==, tarball: file:projects/arm-fabric.tgz} name: '@rush-temp/arm-fabric' version: 0.0.0 dependencies: diff --git a/rush.json b/rush.json index 0ea6400ddf10..d12c99fd89d7 100644 --- a/rush.json +++ b/rush.json @@ -1,7 +1,7 @@ /** * This is the main configuration file for Rush. * For full documentation, please see https://rushjs.io - */ { + */{ "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", /** * (Required) This specifies the version of the Rush engine to be used in this repo. @@ -2296,6 +2296,11 @@ "packageName": "@azure/arm-trustedsigning", "projectFolder": "sdk/trustedsigning/arm-trustedsigning", "versionPolicyName": "management" + }, + { + "packageName": "@azure/arm-contoso", + "projectFolder": "sdk/contoso/arm-contoso", + "versionPolicyName": "management" } ] -} +} \ No newline at end of file diff --git a/sdk/contoso/arm-contoso/CHANGELOG.md b/sdk/contoso/arm-contoso/CHANGELOG.md new file mode 100644 index 000000000000..17ec9628596c --- /dev/null +++ b/sdk/contoso/arm-contoso/CHANGELOG.md @@ -0,0 +1,7 @@ +# Release History + +## 1.0.0-beta.1 (2024-10-26) + +### Features Added + +The package of @azure/arm-contoso is using our next generation design principles. To learn more, please refer to our documentation [Quick Start](https://aka.ms/azsdk/js/mgmt/quickstart). diff --git a/sdk/contoso/arm-contoso/LICENSE b/sdk/contoso/arm-contoso/LICENSE new file mode 100644 index 000000000000..7d5934740965 --- /dev/null +++ b/sdk/contoso/arm-contoso/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/sdk/contoso/arm-contoso/README.md b/sdk/contoso/arm-contoso/README.md new file mode 100644 index 000000000000..fb73ed758158 --- /dev/null +++ b/sdk/contoso/arm-contoso/README.md @@ -0,0 +1,100 @@ +# Azure Contoso client library for JavaScript + +This package contains an isomorphic SDK (runs both in Node.js and in browsers) for Azure Contoso client. + +Microsoft.Contoso Resource Provider management API. + +[Package (NPM)](https://www.npmjs.com/package/@azure/arm-contoso) | +[API reference documentation](https://docs.microsoft.com/javascript/api/@azure/arm-contoso?view=azure-node-preview) | + +## Getting started + +### Currently supported environments + +- [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule) +- Latest versions of Safari, Chrome, Edge and Firefox. + +See our [support policy](https://github.com/Azure/azure-sdk-for-js/blob/main/SUPPORT.md) for more details. + +### Prerequisites + +- An [Azure subscription][azure_sub]. + +### Install the `@azure/arm-contoso` package + +Install the Azure Contoso client library for JavaScript with `npm`: + +```bash +npm install @azure/arm-contoso +``` + +### Create and authenticate a `ContosoClient` + +To create a client object to access the Azure Contoso API, you will need the `endpoint` of your Azure Contoso resource and a `credential`. The Azure Contoso client can use Azure Active Directory credentials to authenticate. +You can find the endpoint for your Azure Contoso resource in the [Azure Portal][azure_portal]. + +You can authenticate with Azure Active Directory using a credential from the [@azure/identity][azure_identity] library or [an existing AAD Token](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/samples/AzureIdentityExamples.md#authenticating-with-a-pre-fetched-access-token). + +To use the [DefaultAzureCredential][defaultazurecredential] provider shown below, or other credential providers provided with the Azure SDK, please install the `@azure/identity` package: + +```bash +npm install @azure/identity +``` + +You will also need to **register a new AAD application and grant access to Azure Contoso** by assigning the suitable role to your service principal (note: roles such as `"Owner"` will not grant the necessary permissions). +Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`. + +For more information about how to create an Azure AD Application check out [this guide](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal). + +```javascript +const { ContosoClient } = require("@azure/arm-contoso"); +const { DefaultAzureCredential } = require("@azure/identity"); +// For client-side applications running in the browser, use InteractiveBrowserCredential instead of DefaultAzureCredential. See https://aka.ms/azsdk/js/identity/examples for more details. + +const subscriptionId = "00000000-0000-0000-0000-000000000000"; +const client = new ContosoClient(new DefaultAzureCredential(), subscriptionId); + +// For client-side applications running in the browser, use this code instead: +// const credential = new InteractiveBrowserCredential({ +// tenantId: "", +// clientId: "" +// }); +// const client = new ContosoClient(credential, subscriptionId); +``` + + +### JavaScript Bundle +To use this client library in the browser, first you need to use a bundler. For details on how to do this, please refer to our [bundling documentation](https://aka.ms/AzureSDKBundling). + +## Key concepts + +### ContosoClient + +`ContosoClient` is the primary interface for developers using the Azure Contoso client library. Explore the methods on this client object to understand the different features of the Azure Contoso service that you can access. + +## Troubleshooting + +### Logging + +Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`: + +```javascript +const { setLogLevel } = require("@azure/logger"); +setLogLevel("info"); +``` + +For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger). + + +## Contributing + +If you'd like to contribute to this library, please read the [contributing guide](https://github.com/Azure/azure-sdk-for-js/blob/main/CONTRIBUTING.md) to learn more about how to build and test the code. + +## Related projects + +- [Microsoft Azure SDK for JavaScript](https://github.com/Azure/azure-sdk-for-js) + +[azure_sub]: https://azure.microsoft.com/free/ +[azure_portal]: https://portal.azure.com +[azure_identity]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity +[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity#defaultazurecredential diff --git a/sdk/contoso/arm-contoso/api-extractor.json b/sdk/contoso/arm-contoso/api-extractor.json new file mode 100644 index 000000000000..923def30f1c0 --- /dev/null +++ b/sdk/contoso/arm-contoso/api-extractor.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "mainEntryPointFilePath": "./dist/esm/index.d.ts", + "docModel": { "enabled": true }, + "apiReport": { "enabled": true, "reportFolder": "./review" }, + "dtsRollup": { + "enabled": true, + "untrimmedFilePath": "", + "publicTrimmedFilePath": "./types/arm-contoso.d.ts" + }, + "messages": { + "tsdocMessageReporting": { "default": { "logLevel": "none" } }, + "extractorMessageReporting": { + "ae-missing-release-tag": { "logLevel": "none" }, + "ae-unresolved-link": { "logLevel": "none" } + } + } +} diff --git a/sdk/contoso/arm-contoso/eslint.config.mjs b/sdk/contoso/arm-contoso/eslint.config.mjs new file mode 100644 index 000000000000..113bdc3eaf5f --- /dev/null +++ b/sdk/contoso/arm-contoso/eslint.config.mjs @@ -0,0 +1,17 @@ +import azsdkEslint from "@azure/eslint-plugin-azure-sdk"; + +export default [ + ...azsdkEslint.configs.recommended, + { + rules: { + "@azure/azure-sdk/ts-modules-only-named": "warn", + "@azure/azure-sdk/ts-apiextractor-json-types": "warn", + "@azure/azure-sdk/ts-package-json-types": "warn", + "@azure/azure-sdk/ts-package-json-engine-is-present": "warn", + "@azure/azure-sdk/ts-package-json-module": "off", + "@azure/azure-sdk/ts-package-json-files-required": "off", + "@azure/azure-sdk/ts-package-json-main-is-cjs": "off", + "tsdoc/syntax": "warn" + } + } +]; diff --git a/sdk/contoso/arm-contoso/package.json b/sdk/contoso/arm-contoso/package.json new file mode 100644 index 000000000000..ad1721ffc946 --- /dev/null +++ b/sdk/contoso/arm-contoso/package.json @@ -0,0 +1,186 @@ +{ + "name": "@azure/arm-contoso", + "version": "1.0.0-beta.1", + "description": "A generated SDK for ContosoClient.", + "engines": { + "node": ">=18.0.0" + }, + "sideEffects": false, + "autoPublish": false, + "tshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts", + "./api": "./src/api/index.ts", + "./models": "./src/models/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "esmDialects": [ + "browser", + "react-native" + ], + "selfLink": false + }, + "type": "module", + "keywords": [ + "node", + "azure", + "cloud", + "typescript", + "browser", + "isomorphic" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "files": [ + "dist", + "README.md", + "LICENSE", + "review/*", + "CHANGELOG.md" + ], + "sdk-type": "mgmt", + "repository": "github:Azure/azure-sdk-for-js", + "bugs": { + "url": "https://github.com/Azure/azure-sdk-for-js/issues" + }, + "prettier": "@azure/eslint-plugin-azure-sdk/prettier.json", + "//metadata": { + "constantPaths": [ + { + "path": "src/rest/contosoClient.ts", + "prefix": "userAgentInfo" + } + ] + }, + "dependencies": { + "@azure/core-util": "^1.9.2", + "@azure-rest/core-client": "^2.1.0", + "@azure/core-auth": "^1.6.0", + "@azure/core-rest-pipeline": "^1.5.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2", + "@azure/core-lro": "^3.0.0", + "@azure/abort-controller": "^2.1.2" + }, + "devDependencies": { + "dotenv": "^16.0.0", + "@microsoft/api-extractor": "^7.40.3", + "@types/node": "^18.0.0", + "eslint": "^8.55.0", + "prettier": "^3.2.5", + "rimraf": "^5.0.5", + "mkdirp": "^3.0.1", + "typescript": "~5.5.3", + "tshy": "^1.11.1", + "@azure/identity": "^4.2.1", + "@vitest/browser": "^2.0.5", + "@vitest/coverage-istanbul": "^2.0.5", + "playwright": "^1.41.2", + "vitest": "^2.0.5", + "@azure-tools/test-credential": "^2.0.0", + "@azure-tools/test-recorder": "^4.0.0", + "@azure/dev-tool": "^1.0.0", + "@azure/eslint-plugin-azure-sdk": "^3.0.0" + }, + "scripts": { + "clean": "rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz *.log", + "extract-api": "rimraf review && mkdirp ./review && dev-tool run extract-api", + "pack": "npm pack 2>&1", + "lint": "eslint package.json api-extractor.json src test", + "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]", + "unit-test": "npm run unit-test:node && npm run unit-test:browser", + "unit-test:browser": "npm run build:test && dev-tool run test:vitest --browser", + "unit-test:node": "dev-tool run test:vitest", + "integration-test": "npm run integration-test:node && npm run integration-test:browser", + "integration-test:browser": "echo skipped", + "integration-test:node": "echo skipped", + "audit": "node ../../../common/scripts/rush-audit.js && rimraf node_modules package-lock.json && npm i --package-lock-only 2>&1 && npm audit", + "build:samples": "echo skipped", + "check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\" ", + "execute:samples": "echo skipped", + "format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\" ", + "generate:client": "echo skipped", + "test:browser": "npm run clean && npm run build:test && npm run unit-test:browser && npm run integration-test:browser", + "minify": "uglifyjs -c -m --comments --source-map \"content='./dist/index.js.map'\" -o ./dist/index.min.js ./dist/index.js", + "build:test": "npm run clean && tshy && dev-tool run build-test", + "build": "npm run clean && tshy && mkdirp ./review && dev-tool run extract-api", + "test:node": "npm run clean && tshy && npm run unit-test:node && npm run integration-test:node", + "test": "npm run clean && tshy && npm run unit-test:node && dev-tool run bundle && npm run unit-test:browser && npm run integration-test" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "browser": { + "source": "./src/index.ts", + "types": "./dist/browser/index.d.ts", + "default": "./dist/browser/index.js" + }, + "react-native": { + "source": "./src/index.ts", + "types": "./dist/react-native/index.d.ts", + "default": "./dist/react-native/index.js" + }, + "import": { + "source": "./src/index.ts", + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "source": "./src/index.ts", + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + }, + "./api": { + "browser": { + "source": "./src/api/index.ts", + "types": "./dist/browser/api/index.d.ts", + "default": "./dist/browser/api/index.js" + }, + "react-native": { + "source": "./src/api/index.ts", + "types": "./dist/react-native/api/index.d.ts", + "default": "./dist/react-native/api/index.js" + }, + "import": { + "source": "./src/api/index.ts", + "types": "./dist/esm/api/index.d.ts", + "default": "./dist/esm/api/index.js" + }, + "require": { + "source": "./src/api/index.ts", + "types": "./dist/commonjs/api/index.d.ts", + "default": "./dist/commonjs/api/index.js" + } + }, + "./models": { + "browser": { + "source": "./src/models/index.ts", + "types": "./dist/browser/models/index.d.ts", + "default": "./dist/browser/models/index.js" + }, + "react-native": { + "source": "./src/models/index.ts", + "types": "./dist/react-native/models/index.d.ts", + "default": "./dist/react-native/models/index.js" + }, + "import": { + "source": "./src/models/index.ts", + "types": "./dist/esm/models/index.d.ts", + "default": "./dist/esm/models/index.js" + }, + "require": { + "source": "./src/models/index.ts", + "types": "./dist/commonjs/models/index.d.ts", + "default": "./dist/commonjs/models/index.js" + } + } + }, + "main": "./dist/commonjs/index.js", + "types": "./dist/commonjs/index.d.ts", + "module": "./dist/esm/index.js" +} diff --git a/sdk/contoso/arm-contoso/review/arm-contoso-api.api.md b/sdk/contoso/arm-contoso/review/arm-contoso-api.api.md new file mode 100644 index 000000000000..360721f12a43 --- /dev/null +++ b/sdk/contoso/arm-contoso/review/arm-contoso-api.api.md @@ -0,0 +1,49 @@ +## API Report File for "@azure/arm-contoso" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Client } from '@azure-rest/core-client'; +import { ClientOptions } from '@azure-rest/core-client'; +import { OperationOptions } from '@azure-rest/core-client'; +import { OperationState } from '@azure/core-lro'; +import { PollerLike } from '@azure/core-lro'; +import { TokenCredential } from '@azure/core-auth'; + +// @public +export interface ContosoClientOptionalParams extends ClientOptions { + apiVersion?: string; +} + +// @public (undocumented) +export interface ContosoContext extends Client { +} + +// @public +export function createContoso(credential: TokenCredential, options?: ContosoClientOptionalParams): ContosoContext; + +// @public +export function employeesCreateOrUpdate(context: ContosoContext, subscriptionId: string, resourceGroupName: string, employeeName: string, resource: Employee, options?: EmployeesCreateOrUpdateOptionalParams): PollerLike, Employee>; + +// @public +export function employeesDelete(context: ContosoContext, subscriptionId: string, resourceGroupName: string, employeeName: string, options?: EmployeesDeleteOptionalParams): PollerLike, void>; + +// @public +export function employeesGet(context: ContosoContext, subscriptionId: string, resourceGroupName: string, employeeName: string, options?: EmployeesGetOptionalParams): Promise; + +// @public +export function employeesListByResourceGroup(context: ContosoContext, subscriptionId: string, resourceGroupName: string, options?: EmployeesListByResourceGroupOptionalParams): PagedAsyncIterableIterator; + +// @public +export function employeesListBySubscription(context: ContosoContext, subscriptionId: string, options?: EmployeesListBySubscriptionOptionalParams): PagedAsyncIterableIterator; + +// @public +export function employeesUpdate(context: ContosoContext, subscriptionId: string, resourceGroupName: string, employeeName: string, properties: EmployeeUpdate, options?: EmployeesUpdateOptionalParams): Promise; + +// @public +export function operationsList(context: ContosoContext, options?: OperationsListOptionalParams): PagedAsyncIterableIterator; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/sdk/contoso/arm-contoso/review/arm-contoso-models.api.md b/sdk/contoso/arm-contoso/review/arm-contoso-models.api.md new file mode 100644 index 000000000000..59dbae08f57d --- /dev/null +++ b/sdk/contoso/arm-contoso/review/arm-contoso-models.api.md @@ -0,0 +1,173 @@ +## API Report File for "@azure/arm-contoso" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { OperationOptions } from '@azure-rest/core-client'; + +// @public +export type ActionType = string; + +// @public +export type CreatedByType = string; + +// @public +export interface Employee extends TrackedResource { + properties?: EmployeeProperties; +} + +// @public +export interface EmployeeProperties { + age?: number; + city?: string; + profile?: Uint8Array; + readonly provisioningState?: ProvisioningState; +} + +// @public +export interface EmployeesCreateOrUpdateOptionalParams extends OperationOptions { + updateIntervalInMs?: number; +} + +// @public +export interface EmployeesDeleteOptionalParams extends OperationOptions { + updateIntervalInMs?: number; +} + +// @public +export interface EmployeesGetOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesListByResourceGroupOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesListBySubscriptionOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesUpdateOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeeUpdate { + properties?: EmployeeUpdateProperties; + tags?: Record; +} + +// @public +export interface EmployeeUpdateProperties { + age?: number; + city?: string; + profile?: Uint8Array; +} + +// @public +export interface ErrorAdditionalInfo { + readonly info?: Record; + readonly type?: string; +} + +// @public +export interface ErrorDetail { + readonly additionalInfo?: ErrorAdditionalInfo[]; + readonly code?: string; + readonly details?: ErrorDetail[]; + readonly message?: string; + readonly target?: string; +} + +// @public +export interface ErrorResponse { + error?: ErrorDetail; +} + +// @public +export enum KnownActionType { + Internal = "Internal" +} + +// @public +export enum KnownCreatedByType { + Application = "Application", + Key = "Key", + ManagedIdentity = "ManagedIdentity", + User = "User" +} + +// @public +export enum KnownOrigin { + "user,system" = "user,system", + system = "system", + user = "user" +} + +// @public +export enum KnownResourceProvisioningState { + Canceled = "Canceled", + Failed = "Failed", + Succeeded = "Succeeded" +} + +// @public +export interface Operation { + actionType?: ActionType; + readonly display?: OperationDisplay; + readonly isDataAction?: boolean; + readonly name?: string; + readonly origin?: Origin; +} + +// @public +export interface OperationDisplay { + readonly description?: string; + readonly operation?: string; + readonly provider?: string; + readonly resource?: string; +} + +// @public +export interface OperationsListOptionalParams extends OperationOptions { +} + +// @public +export type Origin = string; + +// @public +export type ProvisioningState = ResourceProvisioningState | "Provisioning" | "Updating" | "Deleting" | "Accepted" | string; + +// @public +export interface Resource { + readonly id?: string; + readonly name?: string; + readonly systemData?: SystemData; + readonly type?: string; +} + +// @public +export type ResourceProvisioningState = string; + +// @public +export interface SystemData { + createdAt?: Date; + createdBy?: string; + createdByType?: CreatedByType; + lastModifiedAt?: Date; + lastModifiedBy?: string; + lastModifiedByType?: CreatedByType; +} + +// @public +export interface TrackedResource extends Resource { + location: string; + tags?: Record; +} + +// @public +export type Versions = "2021-10-01-preview"; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/sdk/contoso/arm-contoso/review/arm-contoso.api.md b/sdk/contoso/arm-contoso/review/arm-contoso.api.md new file mode 100644 index 000000000000..4f7194232b78 --- /dev/null +++ b/sdk/contoso/arm-contoso/review/arm-contoso.api.md @@ -0,0 +1,235 @@ +## API Report File for "@azure/arm-contoso" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { AbortSignalLike } from '@azure/abort-controller'; +import { ClientOptions } from '@azure-rest/core-client'; +import { OperationOptions } from '@azure-rest/core-client'; +import { OperationState } from '@azure/core-lro'; +import { PathUncheckedResponse } from '@azure-rest/core-client'; +import { Pipeline } from '@azure/core-rest-pipeline'; +import { PollerLike } from '@azure/core-lro'; +import { TokenCredential } from '@azure/core-auth'; + +// @public +export type ActionType = string; + +// @public +export type ContinuablePage = TPage & { + continuationToken?: string; +}; + +// @public (undocumented) +export class ContosoClient { + constructor(credential: TokenCredential, subscriptionId: string, options?: ContosoClientOptionalParams); + readonly employees: EmployeesOperations; + readonly operations: OperationsOperations; + readonly pipeline: Pipeline; +} + +// @public +export interface ContosoClientOptionalParams extends ClientOptions { + apiVersion?: string; +} + +// @public +export type CreatedByType = string; + +// @public +export interface Employee extends TrackedResource { + properties?: EmployeeProperties; +} + +// @public +export interface EmployeeProperties { + age?: number; + city?: string; + profile?: Uint8Array; + readonly provisioningState?: ProvisioningState; +} + +// @public +export interface EmployeesCreateOrUpdateOptionalParams extends OperationOptions { + updateIntervalInMs?: number; +} + +// @public +export interface EmployeesDeleteOptionalParams extends OperationOptions { + updateIntervalInMs?: number; +} + +// @public +export interface EmployeesGetOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesListByResourceGroupOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesListBySubscriptionOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeesOperations { + createOrUpdate: (resourceGroupName: string, employeeName: string, resource: Employee, options?: EmployeesCreateOrUpdateOptionalParams) => PollerLike, Employee>; + delete: (resourceGroupName: string, employeeName: string, options?: EmployeesDeleteOptionalParams) => PollerLike, void>; + get: (resourceGroupName: string, employeeName: string, options?: EmployeesGetOptionalParams) => Promise; + listByResourceGroup: (resourceGroupName: string, options?: EmployeesListByResourceGroupOptionalParams) => PagedAsyncIterableIterator; + listBySubscription: (options?: EmployeesListBySubscriptionOptionalParams) => PagedAsyncIterableIterator; + update: (resourceGroupName: string, employeeName: string, properties: EmployeeUpdate, options?: EmployeesUpdateOptionalParams) => Promise; +} + +// @public +export interface EmployeesUpdateOptionalParams extends OperationOptions { +} + +// @public +export interface EmployeeUpdate { + properties?: EmployeeUpdateProperties; + tags?: Record; +} + +// @public +export interface EmployeeUpdateProperties { + age?: number; + city?: string; + profile?: Uint8Array; +} + +// @public +export interface ErrorAdditionalInfo { + readonly info?: Record; + readonly type?: string; +} + +// @public +export interface ErrorDetail { + readonly additionalInfo?: ErrorAdditionalInfo[]; + readonly code?: string; + readonly details?: ErrorDetail[]; + readonly message?: string; + readonly target?: string; +} + +// @public +export interface ErrorResponse { + error?: ErrorDetail; +} + +// @public +export enum KnownActionType { + Internal = "Internal" +} + +// @public +export enum KnownCreatedByType { + Application = "Application", + Key = "Key", + ManagedIdentity = "ManagedIdentity", + User = "User" +} + +// @public +export enum KnownOrigin { + "user,system" = "user,system", + system = "system", + user = "user" +} + +// @public +export enum KnownResourceProvisioningState { + Canceled = "Canceled", + Failed = "Failed", + Succeeded = "Succeeded" +} + +// @public +export interface Operation { + actionType?: ActionType; + readonly display?: OperationDisplay; + readonly isDataAction?: boolean; + readonly name?: string; + readonly origin?: Origin; +} + +// @public +export interface OperationDisplay { + readonly description?: string; + readonly operation?: string; + readonly provider?: string; + readonly resource?: string; +} + +// @public +export interface OperationsListOptionalParams extends OperationOptions { +} + +// @public +export interface OperationsOperations { + list: (options?: OperationsListOptionalParams) => PagedAsyncIterableIterator; +} + +// @public +export type Origin = string; + +// @public +export interface PagedAsyncIterableIterator { + [Symbol.asyncIterator](): PagedAsyncIterableIterator; + byPage: (settings?: TPageSettings) => AsyncIterableIterator>; + next(): Promise>; +} + +// @public +export interface PageSettings { + continuationToken?: string; +} + +// @public +export type ProvisioningState = ResourceProvisioningState | "Provisioning" | "Updating" | "Deleting" | "Accepted" | string; + +// @public +export interface Resource { + readonly id?: string; + readonly name?: string; + readonly systemData?: SystemData; + readonly type?: string; +} + +// @public +export type ResourceProvisioningState = string; + +// @public +export function restorePoller(client: ContosoClient, serializedState: string, sourceOperation: (...args: any[]) => PollerLike, TResult>, options?: RestorePollerOptions): PollerLike, TResult>; + +// @public (undocumented) +export interface RestorePollerOptions extends OperationOptions { + abortSignal?: AbortSignalLike; + processResponseBody?: (result: TResponse) => Promise; + updateIntervalInMs?: number; +} + +// @public +export interface SystemData { + createdAt?: Date; + createdBy?: string; + createdByType?: CreatedByType; + lastModifiedAt?: Date; + lastModifiedBy?: string; + lastModifiedByType?: CreatedByType; +} + +// @public +export interface TrackedResource extends Resource { + location: string; + tags?: Record; +} + +// @public +export type Versions = "2021-10-01-preview"; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/sdk/contoso/arm-contoso/src/api/contosoContext.ts b/sdk/contoso/arm-contoso/src/api/contosoContext.ts new file mode 100644 index 000000000000..b5c26452433a --- /dev/null +++ b/sdk/contoso/arm-contoso/src/api/contosoContext.ts @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { TokenCredential } from "@azure/core-auth"; +import { ClientOptions, Client, getClient } from "@azure-rest/core-client"; +import { logger } from "../logger.js"; + +export interface ContosoContext extends Client {} + +/** Optional parameters for the client. */ +export interface ContosoClientOptionalParams extends ClientOptions { + /** The API version to use for this operation. */ + apiVersion?: string; +} + +/** Microsoft.Contoso Resource Provider management API. */ +export function createContoso( + credential: TokenCredential, + options: ContosoClientOptionalParams = {}, +): ContosoContext { + const endpointUrl = + options.endpoint ?? options.baseUrl ?? `https://management.azure.com`; + + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-api` + : "azsdk-js-api"; + const { apiVersion: _, ...updatedOptions } = { + ...options, + userAgentOptions: { userAgentPrefix }, + loggingOptions: { logger: options.loggingOptions?.logger ?? logger.info }, + credentials: { + scopes: options.credentials?.scopes ?? [`${endpointUrl}/.default`], + }, + }; + const clientContext = getClient(endpointUrl, credential, updatedOptions); + clientContext.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + const apiVersion = options.apiVersion ?? "2021-10-01-preview"; + clientContext.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version")) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } + + return next(req); + }, + }); + return clientContext; +} diff --git a/sdk/contoso/arm-contoso/src/api/employees/index.ts b/sdk/contoso/arm-contoso/src/api/employees/index.ts new file mode 100644 index 000000000000..8677fe5ec3e2 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/api/employees/index.ts @@ -0,0 +1,533 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + employeePropertiesSerializer, + employeeUpdatePropertiesSerializer, + Employee, + EmployeeUpdate, + _EmployeeListResult, +} from "../../models/models.js"; +import { ContosoContext as Client } from "../index.js"; +import { + StreamableMethod, + operationOptionsToRequestParameters, + PathUncheckedResponse, + createRestError, +} from "@azure-rest/core-client"; +import { serializeRecord } from "../../helpers/serializerHelpers.js"; +import { + PagedAsyncIterableIterator, + buildPagedAsyncIterator, +} from "../../static-helpers/pagingHelpers.js"; +import { getLongRunningPoller } from "../../static-helpers/pollingHelpers.js"; +import { stringToUint8Array } from "@azure/core-util"; +import { PollerLike, OperationState } from "@azure/core-lro"; +import { + EmployeesGetOptionalParams, + EmployeesCreateOrUpdateOptionalParams, + EmployeesUpdateOptionalParams, + EmployeesDeleteOptionalParams, + EmployeesListByResourceGroupOptionalParams, + EmployeesListBySubscriptionOptionalParams, +} from "../../models/options.js"; + +export function _employeesGetSend( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + options: EmployeesGetOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}", + subscriptionId, + resourceGroupName, + employeeName, + ) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _employeesGetDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + tags: result.body["tags"], + location: result.body["location"], + id: result.body["id"], + name: result.body["name"], + type: result.body["type"], + systemData: !result.body.systemData + ? undefined + : { + createdBy: result.body.systemData?.["createdBy"], + createdByType: result.body.systemData?.["createdByType"], + createdAt: + result.body.systemData?.["createdAt"] !== undefined + ? new Date(result.body.systemData?.["createdAt"]) + : undefined, + lastModifiedBy: result.body.systemData?.["lastModifiedBy"], + lastModifiedByType: result.body.systemData?.["lastModifiedByType"], + lastModifiedAt: + result.body.systemData?.["lastModifiedAt"] !== undefined + ? new Date(result.body.systemData?.["lastModifiedAt"]) + : undefined, + }, + properties: !result.body.properties + ? undefined + : { + age: result.body.properties?.["age"], + city: result.body.properties?.["city"], + profile: + typeof result.body.properties?.["profile"] === "string" + ? stringToUint8Array( + result.body.properties?.["profile"], + "base64url", + ) + : result.body.properties?.["profile"], + provisioningState: result.body.properties?.["provisioningState"], + }, + }; +} + +/** Get a Employee */ +export async function employeesGet( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + options: EmployeesGetOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _employeesGetSend( + context, + subscriptionId, + resourceGroupName, + employeeName, + options, + ); + return _employeesGetDeserialize(result); +} + +export function _employeesCreateOrUpdateSend( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + resource: Employee, + options: EmployeesCreateOrUpdateOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}", + subscriptionId, + resourceGroupName, + employeeName, + ) + .put({ + ...operationOptionsToRequestParameters(options), + body: { + tags: !resource.tags + ? resource.tags + : (serializeRecord(resource.tags as any) as any), + location: resource["location"], + properties: !resource.properties + ? resource.properties + : employeePropertiesSerializer(resource.properties), + }, + }); +} + +export async function _employeesCreateOrUpdateDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200", "201"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + tags: result.body["tags"], + location: result.body["location"], + id: result.body["id"], + name: result.body["name"], + type: result.body["type"], + systemData: !result.body.systemData + ? undefined + : { + createdBy: result.body.systemData?.["createdBy"], + createdByType: result.body.systemData?.["createdByType"], + createdAt: + result.body.systemData?.["createdAt"] !== undefined + ? new Date(result.body.systemData?.["createdAt"]) + : undefined, + lastModifiedBy: result.body.systemData?.["lastModifiedBy"], + lastModifiedByType: result.body.systemData?.["lastModifiedByType"], + lastModifiedAt: + result.body.systemData?.["lastModifiedAt"] !== undefined + ? new Date(result.body.systemData?.["lastModifiedAt"]) + : undefined, + }, + properties: !result.body.properties + ? undefined + : { + age: result.body.properties?.["age"], + city: result.body.properties?.["city"], + profile: + typeof result.body.properties?.["profile"] === "string" + ? stringToUint8Array( + result.body.properties?.["profile"], + "base64url", + ) + : result.body.properties?.["profile"], + provisioningState: result.body.properties?.["provisioningState"], + }, + }; +} + +/** Create a Employee */ +export function employeesCreateOrUpdate( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + resource: Employee, + options: EmployeesCreateOrUpdateOptionalParams = { requestOptions: {} }, +): PollerLike, Employee> { + return getLongRunningPoller( + context, + _employeesCreateOrUpdateDeserialize, + ["200", "201"], + { + updateIntervalInMs: options?.updateIntervalInMs, + abortSignal: options?.abortSignal, + getInitialResponse: () => + _employeesCreateOrUpdateSend( + context, + subscriptionId, + resourceGroupName, + employeeName, + resource, + options, + ), + }, + ) as PollerLike, Employee>; +} + +export function _employeesUpdateSend( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + properties: EmployeeUpdate, + options: EmployeesUpdateOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}", + subscriptionId, + resourceGroupName, + employeeName, + ) + .patch({ + ...operationOptionsToRequestParameters(options), + body: { + tags: !properties.tags + ? properties.tags + : (serializeRecord(properties.tags as any) as any), + properties: !properties.properties + ? properties.properties + : employeeUpdatePropertiesSerializer(properties.properties), + }, + }); +} + +export async function _employeesUpdateDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + tags: result.body["tags"], + location: result.body["location"], + id: result.body["id"], + name: result.body["name"], + type: result.body["type"], + systemData: !result.body.systemData + ? undefined + : { + createdBy: result.body.systemData?.["createdBy"], + createdByType: result.body.systemData?.["createdByType"], + createdAt: + result.body.systemData?.["createdAt"] !== undefined + ? new Date(result.body.systemData?.["createdAt"]) + : undefined, + lastModifiedBy: result.body.systemData?.["lastModifiedBy"], + lastModifiedByType: result.body.systemData?.["lastModifiedByType"], + lastModifiedAt: + result.body.systemData?.["lastModifiedAt"] !== undefined + ? new Date(result.body.systemData?.["lastModifiedAt"]) + : undefined, + }, + properties: !result.body.properties + ? undefined + : { + age: result.body.properties?.["age"], + city: result.body.properties?.["city"], + profile: + typeof result.body.properties?.["profile"] === "string" + ? stringToUint8Array( + result.body.properties?.["profile"], + "base64url", + ) + : result.body.properties?.["profile"], + provisioningState: result.body.properties?.["provisioningState"], + }, + }; +} + +/** Update a Employee */ +export async function employeesUpdate( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + properties: EmployeeUpdate, + options: EmployeesUpdateOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _employeesUpdateSend( + context, + subscriptionId, + resourceGroupName, + employeeName, + properties, + options, + ); + return _employeesUpdateDeserialize(result); +} + +export function _employeesDeleteSend( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + options: EmployeesDeleteOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}", + subscriptionId, + resourceGroupName, + employeeName, + ) + .delete({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _employeesDeleteDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["202", "204", "200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return; +} + +/** Delete a Employee */ +export function employeesDelete( + context: Client, + subscriptionId: string, + resourceGroupName: string, + employeeName: string, + options: EmployeesDeleteOptionalParams = { requestOptions: {} }, +): PollerLike, void> { + return getLongRunningPoller( + context, + _employeesDeleteDeserialize, + ["202", "204", "200"], + { + updateIntervalInMs: options?.updateIntervalInMs, + abortSignal: options?.abortSignal, + getInitialResponse: () => + _employeesDeleteSend( + context, + subscriptionId, + resourceGroupName, + employeeName, + options, + ), + }, + ) as PollerLike, void>; +} + +export function _employeesListByResourceGroupSend( + context: Client, + subscriptionId: string, + resourceGroupName: string, + options: EmployeesListByResourceGroupOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees", + subscriptionId, + resourceGroupName, + ) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _employeesListByResourceGroupDeserialize( + result: PathUncheckedResponse, +): Promise<_EmployeeListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + value: result.body["value"].map((p: any) => { + return { + tags: p["tags"], + location: p["location"], + id: p["id"], + name: p["name"], + type: p["type"], + systemData: !p.systemData + ? undefined + : { + createdBy: p.systemData?.["createdBy"], + createdByType: p.systemData?.["createdByType"], + createdAt: + p.systemData?.["createdAt"] !== undefined + ? new Date(p.systemData?.["createdAt"]) + : undefined, + lastModifiedBy: p.systemData?.["lastModifiedBy"], + lastModifiedByType: p.systemData?.["lastModifiedByType"], + lastModifiedAt: + p.systemData?.["lastModifiedAt"] !== undefined + ? new Date(p.systemData?.["lastModifiedAt"]) + : undefined, + }, + properties: !p.properties + ? undefined + : { + age: p.properties?.["age"], + city: p.properties?.["city"], + profile: + typeof p.properties?.["profile"] === "string" + ? stringToUint8Array(p.properties?.["profile"], "base64url") + : p.properties?.["profile"], + provisioningState: p.properties?.["provisioningState"], + }, + }; + }), + nextLink: result.body["nextLink"], + }; +} + +/** List Employee resources by resource group */ +export function employeesListByResourceGroup( + context: Client, + subscriptionId: string, + resourceGroupName: string, + options: EmployeesListByResourceGroupOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => + _employeesListByResourceGroupSend( + context, + subscriptionId, + resourceGroupName, + options, + ), + _employeesListByResourceGroupDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} + +export function _employeesListBySubscriptionSend( + context: Client, + subscriptionId: string, + options: EmployeesListBySubscriptionOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path( + "/subscriptions/{subscriptionId}/providers/Microsoft.Contoso/employees", + subscriptionId, + ) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _employeesListBySubscriptionDeserialize( + result: PathUncheckedResponse, +): Promise<_EmployeeListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + value: result.body["value"].map((p: any) => { + return { + tags: p["tags"], + location: p["location"], + id: p["id"], + name: p["name"], + type: p["type"], + systemData: !p.systemData + ? undefined + : { + createdBy: p.systemData?.["createdBy"], + createdByType: p.systemData?.["createdByType"], + createdAt: + p.systemData?.["createdAt"] !== undefined + ? new Date(p.systemData?.["createdAt"]) + : undefined, + lastModifiedBy: p.systemData?.["lastModifiedBy"], + lastModifiedByType: p.systemData?.["lastModifiedByType"], + lastModifiedAt: + p.systemData?.["lastModifiedAt"] !== undefined + ? new Date(p.systemData?.["lastModifiedAt"]) + : undefined, + }, + properties: !p.properties + ? undefined + : { + age: p.properties?.["age"], + city: p.properties?.["city"], + profile: + typeof p.properties?.["profile"] === "string" + ? stringToUint8Array(p.properties?.["profile"], "base64url") + : p.properties?.["profile"], + provisioningState: p.properties?.["provisioningState"], + }, + }; + }), + nextLink: result.body["nextLink"], + }; +} + +/** List Employee resources by subscription ID */ +export function employeesListBySubscription( + context: Client, + subscriptionId: string, + options: EmployeesListBySubscriptionOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => _employeesListBySubscriptionSend(context, subscriptionId, options), + _employeesListBySubscriptionDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} diff --git a/sdk/contoso/arm-contoso/src/api/index.ts b/sdk/contoso/arm-contoso/src/api/index.ts new file mode 100644 index 000000000000..56978f9370bb --- /dev/null +++ b/sdk/contoso/arm-contoso/src/api/index.ts @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { + createContoso, + ContosoContext, + ContosoClientOptionalParams, +} from "./contosoContext.js"; +export { + employeesGet, + employeesCreateOrUpdate, + employeesUpdate, + employeesDelete, + employeesListByResourceGroup, + employeesListBySubscription, +} from "./employees/index.js"; +export { operationsList } from "./operations/index.js"; diff --git a/sdk/contoso/arm-contoso/src/api/operations/index.ts b/sdk/contoso/arm-contoso/src/api/operations/index.ts new file mode 100644 index 000000000000..f968fa2a312f --- /dev/null +++ b/sdk/contoso/arm-contoso/src/api/operations/index.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { Operation, _OperationListResult } from "../../models/models.js"; +import { ContosoContext as Client } from "../index.js"; +import { + StreamableMethod, + operationOptionsToRequestParameters, + PathUncheckedResponse, + createRestError, +} from "@azure-rest/core-client"; +import { + PagedAsyncIterableIterator, + buildPagedAsyncIterator, +} from "../../static-helpers/pagingHelpers.js"; +import { OperationsListOptionalParams } from "../../models/options.js"; + +export function _operationsListSend( + context: Client, + options: OperationsListOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/providers/Microsoft.Contoso/operations") + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _operationsListDeserialize( + result: PathUncheckedResponse, +): Promise<_OperationListResult> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return { + value: result.body["value"].map((p: any) => { + return { + name: p["name"], + isDataAction: p["isDataAction"], + display: !p.display + ? undefined + : { + provider: p.display?.["provider"], + resource: p.display?.["resource"], + operation: p.display?.["operation"], + description: p.display?.["description"], + }, + origin: p["origin"], + actionType: p["actionType"], + }; + }), + nextLink: result.body["nextLink"], + }; +} + +/** List the operations for the provider */ +export function operationsList( + context: Client, + options: OperationsListOptionalParams = { requestOptions: {} }, +): PagedAsyncIterableIterator { + return buildPagedAsyncIterator( + context, + () => _operationsListSend(context, options), + _operationsListDeserialize, + ["200"], + { itemName: "value", nextLinkName: "nextLink" }, + ); +} diff --git a/sdk/contoso/arm-contoso/src/classic/employees/index.ts b/sdk/contoso/arm-contoso/src/classic/employees/index.ts new file mode 100644 index 000000000000..2d91ee2e20ff --- /dev/null +++ b/sdk/contoso/arm-contoso/src/classic/employees/index.ts @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { ContosoContext } from "../../api/contosoContext.js"; +import { Employee, EmployeeUpdate } from "../../models/models.js"; +import { + employeesGet, + employeesCreateOrUpdate, + employeesUpdate, + employeesDelete, + employeesListByResourceGroup, + employeesListBySubscription, +} from "../../api/employees/index.js"; +import { PagedAsyncIterableIterator } from "../../static-helpers/pagingHelpers.js"; +import { PollerLike, OperationState } from "@azure/core-lro"; +import { + EmployeesGetOptionalParams, + EmployeesCreateOrUpdateOptionalParams, + EmployeesUpdateOptionalParams, + EmployeesDeleteOptionalParams, + EmployeesListByResourceGroupOptionalParams, + EmployeesListBySubscriptionOptionalParams, +} from "../../models/options.js"; + +/** Interface representing a Employees operations. */ +export interface EmployeesOperations { + /** Get a Employee */ + get: ( + resourceGroupName: string, + employeeName: string, + options?: EmployeesGetOptionalParams, + ) => Promise; + /** Create a Employee */ + createOrUpdate: ( + resourceGroupName: string, + employeeName: string, + resource: Employee, + options?: EmployeesCreateOrUpdateOptionalParams, + ) => PollerLike, Employee>; + /** Update a Employee */ + update: ( + resourceGroupName: string, + employeeName: string, + properties: EmployeeUpdate, + options?: EmployeesUpdateOptionalParams, + ) => Promise; + /** Delete a Employee */ + delete: ( + resourceGroupName: string, + employeeName: string, + options?: EmployeesDeleteOptionalParams, + ) => PollerLike, void>; + /** List Employee resources by resource group */ + listByResourceGroup: ( + resourceGroupName: string, + options?: EmployeesListByResourceGroupOptionalParams, + ) => PagedAsyncIterableIterator; + /** List Employee resources by subscription ID */ + listBySubscription: ( + options?: EmployeesListBySubscriptionOptionalParams, + ) => PagedAsyncIterableIterator; +} + +export function getEmployees(context: ContosoContext, subscriptionId: string) { + return { + get: ( + resourceGroupName: string, + employeeName: string, + options?: EmployeesGetOptionalParams, + ) => + employeesGet( + context, + subscriptionId, + resourceGroupName, + employeeName, + options, + ), + createOrUpdate: ( + resourceGroupName: string, + employeeName: string, + resource: Employee, + options?: EmployeesCreateOrUpdateOptionalParams, + ) => + employeesCreateOrUpdate( + context, + subscriptionId, + resourceGroupName, + employeeName, + resource, + options, + ), + update: ( + resourceGroupName: string, + employeeName: string, + properties: EmployeeUpdate, + options?: EmployeesUpdateOptionalParams, + ) => + employeesUpdate( + context, + subscriptionId, + resourceGroupName, + employeeName, + properties, + options, + ), + delete: ( + resourceGroupName: string, + employeeName: string, + options?: EmployeesDeleteOptionalParams, + ) => + employeesDelete( + context, + subscriptionId, + resourceGroupName, + employeeName, + options, + ), + listByResourceGroup: ( + resourceGroupName: string, + options?: EmployeesListByResourceGroupOptionalParams, + ) => + employeesListByResourceGroup( + context, + subscriptionId, + resourceGroupName, + options, + ), + listBySubscription: (options?: EmployeesListBySubscriptionOptionalParams) => + employeesListBySubscription(context, subscriptionId, options), + }; +} + +export function getEmployeesOperations( + context: ContosoContext, + subscriptionId: string, +): EmployeesOperations { + return { + ...getEmployees(context, subscriptionId), + }; +} diff --git a/sdk/contoso/arm-contoso/src/classic/index.ts b/sdk/contoso/arm-contoso/src/classic/index.ts new file mode 100644 index 000000000000..c7df6ab32ba5 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/classic/index.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { EmployeesOperations } from "./employees/index.js"; +export { OperationsOperations } from "./operations/index.js"; diff --git a/sdk/contoso/arm-contoso/src/classic/operations/index.ts b/sdk/contoso/arm-contoso/src/classic/operations/index.ts new file mode 100644 index 000000000000..2350fa435d7a --- /dev/null +++ b/sdk/contoso/arm-contoso/src/classic/operations/index.ts @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { ContosoContext } from "../../api/contosoContext.js"; +import { Operation } from "../../models/models.js"; +import { operationsList } from "../../api/operations/index.js"; +import { PagedAsyncIterableIterator } from "../../static-helpers/pagingHelpers.js"; +import { OperationsListOptionalParams } from "../../models/options.js"; + +/** Interface representing a Operations operations. */ +export interface OperationsOperations { + /** List the operations for the provider */ + list: ( + options?: OperationsListOptionalParams, + ) => PagedAsyncIterableIterator; +} + +export function getOperations(context: ContosoContext) { + return { + list: (options?: OperationsListOptionalParams) => + operationsList(context, options), + }; +} + +export function getOperationsOperations( + context: ContosoContext, +): OperationsOperations { + return { + ...getOperations(context), + }; +} diff --git a/sdk/contoso/arm-contoso/src/contosoClient.ts b/sdk/contoso/arm-contoso/src/contosoClient.ts new file mode 100644 index 000000000000..dd2ca188c1e0 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/contosoClient.ts @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { TokenCredential } from "@azure/core-auth"; +import { Pipeline } from "@azure/core-rest-pipeline"; +import { + getOperationsOperations, + OperationsOperations, +} from "./classic/operations/index.js"; +import { + getEmployeesOperations, + EmployeesOperations, +} from "./classic/employees/index.js"; +import { + createContoso, + ContosoContext, + ContosoClientOptionalParams, +} from "./api/index.js"; + +export { ContosoClientOptionalParams } from "./api/contosoContext.js"; + +export class ContosoClient { + private _client: ContosoContext; + /** The pipeline used by this client to make requests */ + public readonly pipeline: Pipeline; + + /** Microsoft.Contoso Resource Provider management API. */ + constructor( + credential: TokenCredential, + subscriptionId: string, + options: ContosoClientOptionalParams = {}, + ) { + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-client` + : "azsdk-js-client"; + this._client = createContoso(credential, { + ...options, + userAgentOptions: { userAgentPrefix }, + }); + this.pipeline = this._client.pipeline; + this.operations = getOperationsOperations(this._client); + this.employees = getEmployeesOperations(this._client, subscriptionId); + } + + /** The operation groups for Operations */ + public readonly operations: OperationsOperations; + /** The operation groups for Employees */ + public readonly employees: EmployeesOperations; +} diff --git a/sdk/contoso/arm-contoso/src/helpers/serializerHelpers.ts b/sdk/contoso/arm-contoso/src/helpers/serializerHelpers.ts new file mode 100644 index 000000000000..4baaac77c8be --- /dev/null +++ b/sdk/contoso/arm-contoso/src/helpers/serializerHelpers.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export function serializeRecord< + T extends string | number | boolean | Date | null, + R, +>(item: Record): Record; +export function serializeRecord( + item: Record, + serializer: (item: T) => R, +): Record; +export function serializeRecord( + item: Record, + serializer?: (item: T) => R, +): Record { + return Object.keys(item).reduce( + (acc, key) => { + if (isSupportedRecordType(item[key])) { + acc[key] = item[key] as any; + } else if (serializer) { + const value = item[key]; + if (value !== undefined) { + acc[key] = serializer(value); + } + } else { + console.warn(`Don't know how to serialize ${item[key]}`); + acc[key] = item[key] as any; + } + return acc; + }, + {} as Record, + ); +} + +function isSupportedRecordType(t: any) { + return ( + ["number", "string", "boolean", "null"].includes(typeof t) || + t instanceof Date + ); +} diff --git a/sdk/contoso/arm-contoso/src/index.ts b/sdk/contoso/arm-contoso/src/index.ts new file mode 100644 index 000000000000..79f70f48effb --- /dev/null +++ b/sdk/contoso/arm-contoso/src/index.ts @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + PageSettings, + ContinuablePage, + PagedAsyncIterableIterator, +} from "./static-helpers/pagingHelpers.js"; + +export { ContosoClient, ContosoClientOptionalParams } from "./contosoClient.js"; +export { restorePoller, RestorePollerOptions } from "./restorePollerHelpers.js"; +export { + Resource, + SystemData, + KnownCreatedByType, + CreatedByType, + TrackedResource, + Employee, + EmployeeProperties, + KnownResourceProvisioningState, + ResourceProvisioningState, + ErrorResponse, + ErrorDetail, + ErrorAdditionalInfo, + EmployeeUpdate, + EmployeeUpdateProperties, + Operation, + OperationDisplay, + KnownOrigin, + Origin, + KnownActionType, + ActionType, + Versions, + ProvisioningState, + OperationsListOptionalParams, + EmployeesGetOptionalParams, + EmployeesCreateOrUpdateOptionalParams, + EmployeesUpdateOptionalParams, + EmployeesDeleteOptionalParams, + EmployeesListByResourceGroupOptionalParams, + EmployeesListBySubscriptionOptionalParams, +} from "./models/index.js"; +export { EmployeesOperations, OperationsOperations } from "./classic/index.js"; +export { PageSettings, ContinuablePage, PagedAsyncIterableIterator }; diff --git a/sdk/contoso/arm-contoso/src/logger.ts b/sdk/contoso/arm-contoso/src/logger.ts new file mode 100644 index 000000000000..11c43c415a26 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("arm-contoso"); diff --git a/sdk/contoso/arm-contoso/src/models/index.ts b/sdk/contoso/arm-contoso/src/models/index.ts new file mode 100644 index 000000000000..8f281d9c4233 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/models/index.ts @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { + Resource, + SystemData, + KnownCreatedByType, + CreatedByType, + TrackedResource, + Employee, + EmployeeProperties, + KnownResourceProvisioningState, + ResourceProvisioningState, + ErrorResponse, + ErrorDetail, + ErrorAdditionalInfo, + EmployeeUpdate, + EmployeeUpdateProperties, + Operation, + OperationDisplay, + KnownOrigin, + Origin, + KnownActionType, + ActionType, + Versions, + ProvisioningState, +} from "./models.js"; +export { + OperationsListOptionalParams, + EmployeesGetOptionalParams, + EmployeesCreateOrUpdateOptionalParams, + EmployeesUpdateOptionalParams, + EmployeesDeleteOptionalParams, + EmployeesListByResourceGroupOptionalParams, + EmployeesListBySubscriptionOptionalParams, +} from "./options.js"; diff --git a/sdk/contoso/arm-contoso/src/models/models.ts b/sdk/contoso/arm-contoso/src/models/models.ts new file mode 100644 index 000000000000..f098ac18ab7e --- /dev/null +++ b/sdk/contoso/arm-contoso/src/models/models.ts @@ -0,0 +1,298 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { serializeRecord } from "../helpers/serializerHelpers.js"; +import { uint8ArrayToString } from "@azure/core-util"; + +/** Common fields that are returned in the response for all Azure Resource Manager resources */ +export interface Resource { + /** Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} */ + readonly id?: string; + /** The name of the resource */ + readonly name?: string; + /** The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" */ + readonly type?: string; + /** Azure Resource Manager metadata containing createdBy and modifiedBy information. */ + readonly systemData?: SystemData; +} + +export function resourceSerializer(item: Resource) { + return item as any; +} + +/** Metadata pertaining to creation and last modification of the resource. */ +export interface SystemData { + /** The identity that created the resource. */ + createdBy?: string; + /** The type of identity that created the resource. */ + createdByType?: CreatedByType; + /** The timestamp of resource creation (UTC). */ + createdAt?: Date; + /** The identity that last modified the resource. */ + lastModifiedBy?: string; + /** The type of identity that last modified the resource. */ + lastModifiedByType?: CreatedByType; + /** The timestamp of resource last modification (UTC) */ + lastModifiedAt?: Date; +} + +/** Known values of {@link CreatedByType} that the service accepts. */ +export enum KnownCreatedByType { + /** User */ + User = "User", + /** Application */ + Application = "Application", + /** ManagedIdentity */ + ManagedIdentity = "ManagedIdentity", + /** Key */ + Key = "Key", +} + +/** + * The kind of entity that created the resource. \ + * {@link KnownCreatedByType} can be used interchangeably with CreatedByType, + * this enum contains the known values that the service supports. + * ### Known values supported by the service + * **User** \ + * **Application** \ + * **ManagedIdentity** \ + * **Key** + */ +export type CreatedByType = string; + +/** The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location' */ +export interface TrackedResource extends Resource { + /** Resource tags. */ + tags?: Record; + /** The geo-location where the resource lives */ + location: string; +} + +export function trackedResourceSerializer( + item: TrackedResource, +): Record { + return { + tags: !item.tags ? item.tags : (serializeRecord(item.tags as any) as any), + location: item["location"], + }; +} + +/** Employee resource */ +export interface Employee extends TrackedResource { + /** The resource-specific properties for this resource. */ + properties?: EmployeeProperties; +} + +export function employeeSerializer(item: Employee): Record { + return { + tags: !item.tags ? item.tags : (serializeRecord(item.tags as any) as any), + location: item["location"], + properties: !item.properties + ? item.properties + : employeePropertiesSerializer(item.properties), + }; +} + +/** Employee properties */ +export interface EmployeeProperties { + /** Age of employee */ + age?: number; + /** City of employee */ + city?: string; + /** Profile of employee */ + profile?: Uint8Array; + /** The status of the last operation. */ + readonly provisioningState?: ProvisioningState; +} + +export function employeePropertiesSerializer( + item: EmployeeProperties, +): Record { + return { + age: item["age"], + city: item["city"], + profile: + item["profile"] !== undefined + ? uint8ArrayToString(item["profile"], "base64url") + : undefined, + }; +} + +/** Known values of {@link ResourceProvisioningState} that the service accepts. */ +export enum KnownResourceProvisioningState { + /** Succeeded */ + Succeeded = "Succeeded", + /** Failed */ + Failed = "Failed", + /** Canceled */ + Canceled = "Canceled", +} + +/** + * The provisioning state of a resource type. \ + * {@link KnownResourceProvisioningState} can be used interchangeably with ResourceProvisioningState, + * this enum contains the known values that the service supports. + * ### Known values supported by the service + * **Succeeded** \ + * **Failed** \ + * **Canceled** + */ +export type ResourceProvisioningState = string; + +/** Common error response for all Azure Resource Manager APIs to return error details for failed operations. */ +export interface ErrorResponse { + /** The error object. */ + error?: ErrorDetail; +} + +/** The error detail. */ +export interface ErrorDetail { + /** The error code. */ + readonly code?: string; + /** The error message. */ + readonly message?: string; + /** The error target. */ + readonly target?: string; + /** The error details. */ + readonly details?: ErrorDetail[]; + /** The error additional info. */ + readonly additionalInfo?: ErrorAdditionalInfo[]; +} + +/** The resource management error additional info. */ +export interface ErrorAdditionalInfo { + /** The additional info type. */ + readonly type?: string; + /** The additional info. */ + readonly info?: Record; +} + +/** The type used for update operations of the Employee. */ +export interface EmployeeUpdate { + /** Resource tags. */ + tags?: Record; + /** The resource-specific properties for this resource. */ + properties?: EmployeeUpdateProperties; +} + +export function employeeUpdateSerializer( + item: EmployeeUpdate, +): Record { + return { + tags: !item.tags ? item.tags : (serializeRecord(item.tags as any) as any), + properties: !item.properties + ? item.properties + : employeeUpdatePropertiesSerializer(item.properties), + }; +} + +/** The updatable properties of the Employee. */ +export interface EmployeeUpdateProperties { + /** Age of employee */ + age?: number; + /** City of employee */ + city?: string; + /** Profile of employee */ + profile?: Uint8Array; +} + +export function employeeUpdatePropertiesSerializer( + item: EmployeeUpdateProperties, +): Record { + return { + age: item["age"], + city: item["city"], + profile: + item["profile"] !== undefined + ? uint8ArrayToString(item["profile"], "base64url") + : undefined, + }; +} + +/** The response of a Employee list operation. */ +export interface _EmployeeListResult { + /** The Employee items on this page */ + value: Employee[]; + /** The link to the next page of items */ + nextLink?: string; +} + +/** A list of REST API operations supported by an Azure Resource Provider. It contains an URL link to get the next set of results. */ +export interface _OperationListResult { + /** The Operation items on this page */ + value: Operation[]; + /** The link to the next page of items */ + nextLink?: string; +} + +/** Details of a REST API operation, returned from the Resource Provider Operations API */ +export interface Operation { + /** The name of the operation, as per Resource-Based Access Control (RBAC). Examples: "Microsoft.Compute/virtualMachines/write", "Microsoft.Compute/virtualMachines/capture/action" */ + readonly name?: string; + /** Whether the operation applies to data-plane. This is "true" for data-plane operations and "false" for Azure Resource Manager/control-plane operations. */ + readonly isDataAction?: boolean; + /** Localized display information for this particular operation. */ + readonly display?: OperationDisplay; + /** The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is "user,system" */ + readonly origin?: Origin; + /** Extensible enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. */ + actionType?: ActionType; +} + +/** Localized display information for and operation. */ +export interface OperationDisplay { + /** The localized friendly form of the resource provider name, e.g. "Microsoft Monitoring Insights" or "Microsoft Compute". */ + readonly provider?: string; + /** The localized friendly name of the resource type related to this operation. E.g. "Virtual Machines" or "Job Schedule Collections". */ + readonly resource?: string; + /** The concise, localized friendly name for the operation; suitable for dropdowns. E.g. "Create or Update Virtual Machine", "Restart Virtual Machine". */ + readonly operation?: string; + /** The short, localized friendly description of the operation; suitable for tool tips and detailed views. */ + readonly description?: string; +} + +/** Known values of {@link Origin} that the service accepts. */ +export enum KnownOrigin { + /** user */ + user = "user", + /** system */ + system = "system", + /** user,system */ + "user,system" = "user,system", +} + +/** + * The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is "user,system" \ + * {@link KnownOrigin} can be used interchangeably with Origin, + * this enum contains the known values that the service supports. + * ### Known values supported by the service + * **user** \ + * **system** \ + * **user,system** + */ +export type Origin = string; + +/** Known values of {@link ActionType} that the service accepts. */ +export enum KnownActionType { + /** Internal */ + Internal = "Internal", +} + +/** + * Extensible enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. \ + * {@link KnownActionType} can be used interchangeably with ActionType, + * this enum contains the known values that the service supports. + * ### Known values supported by the service + * **Internal** + */ +export type ActionType = string; +/** The available API versions. */ +export type Versions = "2021-10-01-preview"; +/** Alias for ProvisioningState */ +export type ProvisioningState = + | ResourceProvisioningState + | "Provisioning" + | "Updating" + | "Deleting" + | "Accepted" + | string; diff --git a/sdk/contoso/arm-contoso/src/models/options.ts b/sdk/contoso/arm-contoso/src/models/options.ts new file mode 100644 index 000000000000..f795d7e9d13d --- /dev/null +++ b/sdk/contoso/arm-contoso/src/models/options.ts @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { OperationOptions } from "@azure-rest/core-client"; + +/** Optional parameters. */ +export interface OperationsListOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface EmployeesGetOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface EmployeesCreateOrUpdateOptionalParams + extends OperationOptions { + /** Delay to wait until next poll, in milliseconds. */ + updateIntervalInMs?: number; +} + +/** Optional parameters. */ +export interface EmployeesUpdateOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface EmployeesDeleteOptionalParams extends OperationOptions { + /** Delay to wait until next poll, in milliseconds. */ + updateIntervalInMs?: number; +} + +/** Optional parameters. */ +export interface EmployeesListByResourceGroupOptionalParams + extends OperationOptions {} + +/** Optional parameters. */ +export interface EmployeesListBySubscriptionOptionalParams + extends OperationOptions {} diff --git a/sdk/contoso/arm-contoso/src/restorePollerHelpers.ts b/sdk/contoso/arm-contoso/src/restorePollerHelpers.ts new file mode 100644 index 000000000000..b249649f0b91 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/restorePollerHelpers.ts @@ -0,0 +1,174 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { ContosoClient } from "./contosoClient.js"; +import { + _employeesCreateOrUpdateDeserialize, + _employeesDeleteDeserialize, +} from "./api/employees/index.js"; +import { getLongRunningPoller } from "./static-helpers/pollingHelpers.js"; +import { + OperationOptions, + PathUncheckedResponse, +} from "@azure-rest/core-client"; +import { AbortSignalLike } from "@azure/abort-controller"; +import { + PollerLike, + OperationState, + deserializeState, + ResourceLocationConfig, +} from "@azure/core-lro"; + +export interface RestorePollerOptions< + TResult, + TResponse extends PathUncheckedResponse = PathUncheckedResponse, +> extends OperationOptions { + /** Delay to wait until next poll, in milliseconds. */ + updateIntervalInMs?: number; + /** + * The signal which can be used to abort requests. + */ + abortSignal?: AbortSignalLike; + /** Deserialization function for raw response body */ + processResponseBody?: (result: TResponse) => Promise; +} + +/** + * Creates a poller from the serialized state of another poller. This can be + * useful when you want to create pollers on a different host or a poller + * needs to be constructed after the original one is not in scope. + */ +export function restorePoller( + client: ContosoClient, + serializedState: string, + sourceOperation: ( + ...args: any[] + ) => PollerLike, TResult>, + options?: RestorePollerOptions, +): PollerLike, TResult> { + const pollerConfig = deserializeState(serializedState).config; + const { initialRequestUrl, requestMethod, metadata } = pollerConfig; + if (!initialRequestUrl || !requestMethod) { + throw new Error( + `Invalid serialized state: ${serializedState} for sourceOperation ${sourceOperation?.name}`, + ); + } + const resourceLocationConfig = metadata?.["resourceLocationConfig"] as + | ResourceLocationConfig + | undefined; + const { deserializer, expectedStatuses = [] } = + getDeserializationHelper(initialRequestUrl, requestMethod) ?? {}; + const deserializeHelper = options?.processResponseBody ?? deserializer; + if (!deserializeHelper) { + throw new Error( + `Please ensure the operation is in this client! We can't find its deserializeHelper for ${sourceOperation?.name}.`, + ); + } + return getLongRunningPoller( + (client as any)["_client"] ?? client, + deserializeHelper as (result: TResponse) => Promise, + expectedStatuses, + { + updateIntervalInMs: options?.updateIntervalInMs, + abortSignal: options?.abortSignal, + resourceLocationConfig, + restoreFrom: serializedState, + initialRequestUrl, + }, + ); +} + +interface DeserializationHelper { + deserializer: Function; + expectedStatuses: string[]; +} + +const deserializeMap: Record = { + "PUT /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": + { + deserializer: _employeesCreateOrUpdateDeserialize, + expectedStatuses: ["200", "201"], + }, + "DELETE /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": + { + deserializer: _employeesDeleteDeserialize, + expectedStatuses: ["202", "204", "200"], + }, +}; + +function getDeserializationHelper( + urlStr: string, + method: string, +): DeserializationHelper | undefined { + const path = new URL(urlStr).pathname; + const pathParts = path.split("/"); + + // Traverse list to match the longest candidate + // matchedLen: the length of candidate path + // matchedValue: the matched status code array + let matchedLen = -1, + matchedValue: DeserializationHelper | undefined; + + // Iterate the responseMap to find a match + for (const [key, value] of Object.entries(deserializeMap)) { + // Extracting the path from the map key which is in format + // GET /path/foo + if (!key.startsWith(method)) { + continue; + } + const candidatePath = getPathFromMapKey(key); + // Get each part of the url path + const candidateParts = candidatePath.split("/"); + + // track if we have found a match to return the values found. + let found = true; + for ( + let i = candidateParts.length - 1, j = pathParts.length - 1; + i >= 1 && j >= 1; + i--, j-- + ) { + if ( + candidateParts[i]?.startsWith("{") && + candidateParts[i]?.indexOf("}") !== -1 + ) { + const start = candidateParts[i]!.indexOf("}") + 1, + end = candidateParts[i]?.length; + // If the current part of the candidate is a "template" part + // Try to use the suffix of pattern to match the path + // {guid} ==> $ + // {guid}:export ==> :export$ + const isMatched = new RegExp( + `${candidateParts[i]?.slice(start, end)}`, + ).test(pathParts[j] || ""); + + if (!isMatched) { + found = false; + break; + } + continue; + } + + // If the candidate part is not a template and + // the parts don't match mark the candidate as not found + // to move on with the next candidate path. + if (candidateParts[i] !== pathParts[j]) { + found = false; + break; + } + } + + // We finished evaluating the current candidate parts + // Update the matched value if and only if we found the longer pattern + if (found && candidatePath.length > matchedLen) { + matchedLen = candidatePath.length; + matchedValue = value; + } + } + + return matchedValue; +} + +function getPathFromMapKey(mapKey: string): string { + const pathStart = mapKey.indexOf("/"); + return mapKey.slice(pathStart); +} diff --git a/sdk/contoso/arm-contoso/src/static-helpers/pagingHelpers.ts b/sdk/contoso/arm-contoso/src/static-helpers/pagingHelpers.ts new file mode 100644 index 000000000000..dc35b0af242d --- /dev/null +++ b/sdk/contoso/arm-contoso/src/static-helpers/pagingHelpers.ts @@ -0,0 +1,277 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + Client, + createRestError, + PathUncheckedResponse, +} from "@azure-rest/core-client"; +import { RestError } from "@azure/core-rest-pipeline"; + +/** + * Options for the byPage method + */ +export interface PageSettings { + /** + * A reference to a specific page to start iterating from. + */ + continuationToken?: string; +} + +/** + * An interface that describes a page of results. + */ +export type ContinuablePage = TPage & { + /** + * The token that keeps track of where to continue the iterator + */ + continuationToken?: string; +}; + +/** + * An interface that allows async iterable iteration both to completion and by page. + */ +export interface PagedAsyncIterableIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +> { + /** + * The next method, part of the iteration protocol + */ + next(): Promise>; + /** + * The connection to the async iterator, part of the iteration protocol + */ + [Symbol.asyncIterator](): PagedAsyncIterableIterator< + TElement, + TPage, + TPageSettings + >; + /** + * Return an AsyncIterableIterator that works a page at a time + */ + byPage: ( + settings?: TPageSettings, + ) => AsyncIterableIterator>; +} + +/** + * An interface that describes how to communicate with the service. + */ +export interface PagedResult< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +> { + /** + * Link to the first page of results. + */ + firstPageLink?: string; + /** + * A method that returns a page of results. + */ + getPage: ( + pageLink?: string, + ) => Promise<{ page: TPage; nextPageLink?: string } | undefined>; + /** + * a function to implement the `byPage` method on the paged async iterator. + */ + byPage?: ( + settings?: TPageSettings, + ) => AsyncIterableIterator>; + + /** + * A function to extract elements from a page. + */ + toElements?: (page: TPage) => TElement[]; +} + +/** + * Options for the paging helper + */ +export interface BuildPagedAsyncIteratorOptions { + itemName?: string; + nextLinkName?: string; +} + +/** + * Helper to paginate results in a generic way and return a PagedAsyncIterableIterator + */ +export function buildPagedAsyncIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, + TResponse extends PathUncheckedResponse = PathUncheckedResponse, +>( + client: Client, + getInitialResponse: () => PromiseLike, + processResponseBody: (result: TResponse) => PromiseLike, + expectedStatuses: string[], + options: BuildPagedAsyncIteratorOptions = {}, +): PagedAsyncIterableIterator { + const itemName = options.itemName ?? "value"; + const nextLinkName = options.nextLinkName ?? "nextLink"; + const pagedResult: PagedResult = { + getPage: async (pageLink?: string) => { + const result = + pageLink === undefined + ? await getInitialResponse() + : await client.pathUnchecked(pageLink).get(); + checkPagingRequest(result, expectedStatuses); + const results = await processResponseBody(result as TResponse); + const nextLink = getNextLink(results, nextLinkName); + const values = getElements(results, itemName) as TPage; + return { + page: values, + nextPageLink: nextLink, + }; + }, + byPage: (settings?: TPageSettings) => { + const { continuationToken } = settings ?? {}; + return getPageAsyncIterator(pagedResult, { + pageLink: continuationToken, + }); + }, + }; + return getPagedAsyncIterator(pagedResult); +} + +/** + * returns an async iterator that iterates over results. It also has a `byPage` + * method that returns pages of items at once. + * + * @param pagedResult - an object that specifies how to get pages. + * @returns a paged async iterator that iterates over results. + */ + +function getPagedAsyncIterator< + TElement, + TPage = TElement[], + TPageSettings extends PageSettings = PageSettings, +>( + pagedResult: PagedResult, +): PagedAsyncIterableIterator { + const iter = getItemAsyncIterator( + pagedResult, + ); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: + pagedResult?.byPage ?? + ((settings?: TPageSettings) => { + const { continuationToken } = settings ?? {}; + return getPageAsyncIterator(pagedResult, { + pageLink: continuationToken, + }); + }), + }; +} + +async function* getItemAsyncIterator< + TElement, + TPage, + TPageSettings extends PageSettings, +>( + pagedResult: PagedResult, +): AsyncIterableIterator { + const pages = getPageAsyncIterator(pagedResult); + for await (const page of pages) { + yield* page as unknown as TElement[]; + } +} + +async function* getPageAsyncIterator< + TElement, + TPage, + TPageSettings extends PageSettings, +>( + pagedResult: PagedResult, + options: { + pageLink?: string; + } = {}, +): AsyncIterableIterator> { + const { pageLink } = options; + let response = await pagedResult.getPage( + pageLink ?? pagedResult.firstPageLink, + ); + if (!response) { + return; + } + let result = response.page as ContinuablePage; + result.continuationToken = response.nextPageLink; + yield result; + while (response.nextPageLink) { + response = await pagedResult.getPage(response.nextPageLink); + if (!response) { + return; + } + result = response.page as ContinuablePage; + result.continuationToken = response.nextPageLink; + yield result; + } +} + +/** + * Gets for the value of nextLink in the body + */ +function getNextLink(body: unknown, nextLinkName?: string): string | undefined { + if (!nextLinkName) { + return undefined; + } + + const nextLink = (body as Record)[nextLinkName]; + + if ( + typeof nextLink !== "string" && + typeof nextLink !== "undefined" && + nextLink !== null + ) { + throw new RestError( + `Body Property ${nextLinkName} should be a string or undefined or null but got ${typeof nextLink}`, + ); + } + + if (nextLink === null) { + return undefined; + } + + return nextLink; +} + +/** + * Gets the elements of the current request in the body. + */ +function getElements(body: unknown, itemName: string): T[] { + const value = (body as Record)[itemName] as T[]; + if (!Array.isArray(value)) { + throw new RestError( + `Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`, + ); + } + + return value ?? []; +} + +/** + * Checks if a request failed + */ +function checkPagingRequest( + response: PathUncheckedResponse, + expectedStatuses: string[], +): void { + if (!expectedStatuses.includes(response.status)) { + throw createRestError( + `Pagination failed with unexpected statusCode ${response.status}`, + response, + ); + } +} diff --git a/sdk/contoso/arm-contoso/src/static-helpers/pollingHelpers.ts b/sdk/contoso/arm-contoso/src/static-helpers/pollingHelpers.ts new file mode 100644 index 000000000000..87a63b1fc5d1 --- /dev/null +++ b/sdk/contoso/arm-contoso/src/static-helpers/pollingHelpers.ts @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + PollerLike, + OperationState, + ResourceLocationConfig, + RunningOperation, + createHttpPoller, + OperationResponse, +} from "@azure/core-lro"; + +import { + Client, + PathUncheckedResponse, + createRestError, +} from "@azure-rest/core-client"; +import { AbortSignalLike } from "@azure/abort-controller"; + +export interface GetLongRunningPollerOptions { + /** Delay to wait until next poll, in milliseconds. */ + updateIntervalInMs?: number; + /** + * The signal which can be used to abort requests. + */ + abortSignal?: AbortSignalLike; + /** + * The potential location of the result of the LRO if specified by the LRO extension in the swagger. + */ + resourceLocationConfig?: ResourceLocationConfig; + /** + * The original url of the LRO + * Should not be null when restoreFrom is set + */ + initialRequestUrl?: string; + /** + * A serialized poller which can be used to resume an existing paused Long-Running-Operation. + */ + restoreFrom?: string; + /** + * The function to get the initial response + */ + getInitialResponse?: () => PromiseLike; +} +export function getLongRunningPoller< + TResponse extends PathUncheckedResponse, + TResult = void, +>( + client: Client, + processResponseBody: (result: TResponse) => Promise, + expectedStatuses: string[], + options: GetLongRunningPollerOptions, +): PollerLike, TResult> { + const { restoreFrom, getInitialResponse } = options; + if (!restoreFrom && !getInitialResponse) { + throw new Error( + "Either restoreFrom or getInitialResponse must be specified", + ); + } + let initialResponse: TResponse | undefined = undefined; + const pollAbortController = new AbortController(); + const poller: RunningOperation = { + sendInitialRequest: async () => { + if (!getInitialResponse) { + throw new Error( + "getInitialResponse is required when initializing a new poller", + ); + } + initialResponse = await getInitialResponse(); + return getLroResponse(initialResponse, expectedStatuses); + }, + sendPollRequest: async ( + path: string, + pollOptions?: { + abortSignal?: AbortSignalLike; + }, + ) => { + // The poll request would both listen to the user provided abort signal and the poller's own abort signal + function abortListener(): void { + pollAbortController.abort(); + } + const abortSignal = pollAbortController.signal; + if (options.abortSignal?.aborted) { + pollAbortController.abort(); + } else if (pollOptions?.abortSignal?.aborted) { + pollAbortController.abort(); + } else if (!abortSignal.aborted) { + options.abortSignal?.addEventListener("abort", abortListener, { + once: true, + }); + pollOptions?.abortSignal?.addEventListener("abort", abortListener, { + once: true, + }); + } + let response; + try { + response = await client.pathUnchecked(path).get({ abortSignal }); + } finally { + options.abortSignal?.removeEventListener("abort", abortListener); + pollOptions?.abortSignal?.removeEventListener("abort", abortListener); + } + + return getLroResponse(response as TResponse, expectedStatuses); + }, + }; + return createHttpPoller(poller, { + intervalInMs: options?.updateIntervalInMs, + resourceLocationConfig: options?.resourceLocationConfig, + restoreFrom: options?.restoreFrom, + processResult: (result: unknown) => { + return processResponseBody(result as TResponse); + }, + }); +} +/** + * Converts a Rest Client response to a response that the LRO implementation understands + * @param response - a rest client http response + * @param deserializeFn - deserialize function to convert Rest response to modular output + * @returns - An LRO response that the LRO implementation understands + */ +function getLroResponse( + response: TResponse, + expectedStatuses: string[], +): OperationResponse { + if (!expectedStatuses.includes(response.status)) { + throw createRestError(response); + } + + return { + flatResponse: response, + rawResponse: { + ...response, + statusCode: Number.parseInt(response.status), + body: response.body, + }, + }; +} diff --git a/sdk/contoso/arm-contoso/test/public/sampleTest.spec.ts b/sdk/contoso/arm-contoso/test/public/sampleTest.spec.ts new file mode 100644 index 000000000000..d4919ac91ac5 --- /dev/null +++ b/sdk/contoso/arm-contoso/test/public/sampleTest.spec.ts @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createRecorder } from "./utils/recordedClient.js"; +import { assert, beforeEach, afterEach, it, describe } from "vitest"; + +describe("My test", () => { + // let recorder: Recorder; + + beforeEach(async function () { + // recorder = await createRecorder(this); + }); + + afterEach(async function () { + // await recorder.stop(); + }); + + it("sample test", async function () { + assert.equal(1, 1); + }); +}); diff --git a/sdk/contoso/arm-contoso/test/public/utils/recordedClient.ts b/sdk/contoso/arm-contoso/test/public/utils/recordedClient.ts new file mode 100644 index 000000000000..6e425fdcfdf9 --- /dev/null +++ b/sdk/contoso/arm-contoso/test/public/utils/recordedClient.ts @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + Recorder, + RecorderStartOptions, + VitestTestContext, +} from "@azure-tools/test-recorder"; + +const replaceableVariables: Record = { + SUBSCRIPTION_ID: "azure_subscription_id", +}; + +const recorderEnvSetup: RecorderStartOptions = { + envSetupForPlayback: replaceableVariables, +}; + +/** + * creates the recorder and reads the environment variables from the `.env` file. + * Should be called first in the test suite to make sure environment variables are + * read before they are being used. + */ +export async function createRecorder( + context: VitestTestContext, +): Promise { + const recorder = new Recorder(context); + await recorder.start(recorderEnvSetup); + return recorder; +} diff --git a/sdk/contoso/arm-contoso/tsconfig.browser.config.json b/sdk/contoso/arm-contoso/tsconfig.browser.config.json new file mode 100644 index 000000000000..1b37aebc5457 --- /dev/null +++ b/sdk/contoso/arm-contoso/tsconfig.browser.config.json @@ -0,0 +1,10 @@ +{ + "extends": "./.tshy/build.json", + "include": ["./src/**/*.ts", "./src/**/*.mts", "./test/**/*.spec.ts"], + "exclude": ["./test/**/node/**/*.ts"], + "compilerOptions": { + "outDir": "./dist-test/browser", + "rootDir": ".", + "skipLibCheck": true + } +} diff --git a/sdk/contoso/arm-contoso/tsconfig.json b/sdk/contoso/arm-contoso/tsconfig.json new file mode 100644 index 000000000000..8c962911295c --- /dev/null +++ b/sdk/contoso/arm-contoso/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": ".", + "skipLibCheck": true + }, + "include": [ + "./src/**/*.ts", + "./src/**/*.mts", + "./src/**/*.cts", + "test/**/*.ts", + "./test/**/*.ts" + ] +} diff --git a/sdk/contoso/arm-contoso/tsp-location.yaml b/sdk/contoso/arm-contoso/tsp-location.yaml new file mode 100644 index 000000000000..172d0953d662 --- /dev/null +++ b/sdk/contoso/arm-contoso/tsp-location.yaml @@ -0,0 +1,4 @@ +directory: specification/contosowidgetmanager/Contoso.Management +commit: bcb0828be4c68bb322dad340395dae1e91901983 +repo: ../azure-rest-api-specs +additionalDirectories: diff --git a/sdk/contoso/arm-contoso/vitest.browser.config.ts b/sdk/contoso/arm-contoso/vitest.browser.config.ts new file mode 100644 index 000000000000..5e0dc418cfa2 --- /dev/null +++ b/sdk/contoso/arm-contoso/vitest.browser.config.ts @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig } from "vitest/config"; +import { relativeRecordingsPath } from "@azure-tools/test-recorder"; + +process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath(); + +export default defineConfig({ + define: { + "process.env": process.env, + }, + test: { + reporters: ["basic", "junit"], + outputFile: { + junit: "test-results.browser.xml", + }, + browser: { + enabled: true, + headless: true, + name: "chromium", + provider: "playwright", + }, + fakeTimers: { + toFake: ["setTimeout", "Date"], + }, + watch: false, + include: ["dist-test/browser/**/*.spec.js"], + coverage: { + include: ["dist-test/browser/**/*.spec.js"], + provider: "istanbul", + reporter: ["text", "json", "html"], + reportsDirectory: "coverage-browser", + }, + testTimeout: 1200000, + }, +}); diff --git a/sdk/contoso/arm-contoso/vitest.config.ts b/sdk/contoso/arm-contoso/vitest.config.ts new file mode 100644 index 000000000000..f8ab2a758bf9 --- /dev/null +++ b/sdk/contoso/arm-contoso/vitest.config.ts @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { defineConfig } from "vitest/config"; +import { relativeRecordingsPath } from "@azure-tools/test-recorder"; + +export default defineConfig({ + test: { + reporters: ["basic", "junit"], + outputFile: { + junit: "test-results.browser.xml", + }, + fakeTimers: { + toFake: ["setTimeout", "Date"], + }, + watch: false, + include: ["test/**/*.spec.ts"], + exclude: ["test/**/browser/*.spec.ts"], + coverage: { + include: ["src/**/*.ts"], + exclude: [ + "src/**/*-browser.mts", + "src/**/*-react-native.mts", + "vitest*.config.ts", + "samples-dev/**/*.ts", + ], + provider: "istanbul", + reporter: ["text", "json", "html"], + reportsDirectory: "coverage", + }, + testTimeout: 1200000, + }, +}); diff --git a/sdk/contoso/ci.mgmt.yml b/sdk/contoso/ci.mgmt.yml new file mode 100644 index 000000000000..1c9c2fd296e4 --- /dev/null +++ b/sdk/contoso/ci.mgmt.yml @@ -0,0 +1,35 @@ +# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file. + +trigger: + branches: + include: + - main + - feature/* + - release/* + - hotfix/* + exclude: + - feature/v4 + paths: + include: + - sdk/contoso/arm-contoso + - sdk/contoso/ci.mgmt.yml +pr: + branches: + include: + - main + - feature/* + - release/* + - hotfix/* + exclude: + - feature/v4 + paths: + include: + - sdk/contoso/arm-contoso + - sdk/contoso/ci.mgmt.yml +extends: + template: /eng/pipelines/templates/stages/archetype-sdk-client.yml + parameters: + ServiceDirectory: sdk/contoso + Artifacts: + - name: azure-arm-contoso + safeName: azurearmcontoso