From a5a2e030ac984ae94ab97d93e1decdd425ca5dc9 Mon Sep 17 00:00:00 2001 From: derek Date: Thu, 15 Oct 2020 10:22:40 +0800 Subject: [PATCH 1/5] Clean m3 related steps from the pipeline --- powershell/autorest-configuration.md | 52 ++-------------------------- 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/powershell/autorest-configuration.md b/powershell/autorest-configuration.md index 2c9dd6aaca..d6b1cf3530 100644 --- a/powershell/autorest-configuration.md +++ b/powershell/autorest-configuration.md @@ -16,9 +16,8 @@ modelerfour: > if the modeler is loaded already, use that one, otherwise grab it. -``` yaml +``` yaml !isLoaded('@autorest/modelerfour') use-extension: - "@autorest/remodeler" : "~2.1.0" "@autorest/modelerfour": "4.15.414" # will use highest 2.0.x @@ -105,24 +104,6 @@ declare-directive: # Pipeline Configuration ``` yaml pipeline: -# --- extension remodeler --- - - # "Shake the tree", and normalize the model - remodeler: - input: openapi-document/multi-api/identity # the plugin where we get inputs from - - # allow developer to do transformations on the code model. - remodeler/new-transform: - input: remodeler - - # Make some interpretations about what some things in the model mean - tweakcodemodel: - input: remodeler/new-transform - - # Specific things for Azure - tweakcodemodelazure: - input: tweakcodemodel - # --- extension powershell based on modelerfour # Fix the code model gap between m3 and m4 @@ -159,44 +140,15 @@ pipeline: powershell-v2: input: add-azure-completers-v2 -# --- extension powershell --- - - # creates high-level commands - create-commands: - input: tweakcodemodelazure # brings the code-model-v3 with it. - - create-virtual-properties: - input: create-commands - - # Choose names for everything in c# - csnamer: - input: create-virtual-properties # and the generated c# files - - # ensures that names/descriptions are properly set for powershell - psnamer: - input: csnamer - - modifiers: - input: psnamer - - add-azure-completers: - input: modifiers - - # creates powershell cmdlets for high-level commands. (leverages llc# code) - powershell: - input: add-azure-completers # and the generated c# files # --- extension llcsharp --- # generates c# files for http-operations - llcsharp: - input: modifiers - llcsharp/text-transform: input: llcsharp-v2 scope: scope-here powershell/text-transform: - input: powershell-v2 + input: powershell-v2 scope: scope-here llcsharp/emitter: From 71ef51380212a970c4987c37aac00344db2b71b4 Mon Sep 17 00:00:00 2001 From: derek Date: Thu, 15 Oct 2020 13:13:24 +0800 Subject: [PATCH 2/5] clean m3 plugins and update related tests accordingly --- common/config/rush/pnpm-lock.yaml | 3152 +++++++++++++++++ common/scripts/install-run-rush.js | 27 +- common/scripts/install-run.js | 349 +- powershell/main.ts | 21 +- powershell/plugins/add-azure-completers.ts | 47 - powershell/plugins/create-commands.ts | 454 --- powershell/plugins/cs-namer.ts | 245 -- powershell/plugins/llcsharp.ts | 77 - powershell/plugins/modifiers.ts | 701 ---- .../plugins/plugin-tweak-model-azure.ts | 175 - powershell/plugins/powershell.ts | 82 - powershell/plugins/ps-namer.ts | 201 -- powershell/test/noun-cleaning.ts | 2 +- powershell/test/operationId-inferring.ts | 2 +- powershell/test/test-service-name.ts | 2 +- 15 files changed, 3386 insertions(+), 2151 deletions(-) create mode 100644 common/config/rush/pnpm-lock.yaml delete mode 100644 powershell/plugins/add-azure-completers.ts delete mode 100644 powershell/plugins/create-commands.ts delete mode 100644 powershell/plugins/cs-namer.ts delete mode 100644 powershell/plugins/llcsharp.ts delete mode 100644 powershell/plugins/modifiers.ts delete mode 100644 powershell/plugins/plugin-tweak-model-azure.ts delete mode 100644 powershell/plugins/powershell.ts delete mode 100644 powershell/plugins/ps-namer.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml new file mode 100644 index 0000000000..197ca8b039 --- /dev/null +++ b/common/config/rush/pnpm-lock.yaml @@ -0,0 +1,3152 @@ +dependencies: + '@autorest/autorest': 3.0.6187 + '@azure-tools/async-io': 3.0.252 + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/codegen-csharp': 3.0.262 + '@azure-tools/codemodel': 4.13.348 + '@azure-tools/codemodel-v3': 3.1.264 + '@azure-tools/linq': 3.1.261 + '@azure-tools/tasks': 3.0.252 + '@microsoft.azure/autorest.testserver': 2.9.9 + '@rush-temp/powershell': 'file:projects/powershell.tgz' + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': 2.0.0_b7c2671679a3bd4e1f52a3d3da16606f + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: 3.7.5 + xmlbuilder: 10.1.1 +lockfileVersion: 5.1 +packages: + /@autorest/autorest/3.0.6187: + dev: false + engines: + node: '>=10.13.0' + hasBin: true + requiresBuild: true + resolution: + integrity: sha512-BUTLfV6GufjgcSp0ysB1wdhMIG8RGQMiY4ZQnP76fHcR2KZW0QinnEAR99mMy7BVOdXiurWkNW7rilEJfKhXWg== + /@azure-tools/async-io/3.0.252: + dependencies: + '@azure-tools/tasks': 3.0.252 + proper-lockfile: 2.0.1 + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-RpoaEWGwpdp4FR9YKgnSkvwhdeR1gIzRFFOBotOyd3ow8FMfRIvMZ/eHar2iM3OXUnRKbHnv1M6oapdZah1JWw== + /@azure-tools/autorest-extension-base/3.1.266: + dependencies: + '@azure-tools/codegen': 2.5.290 + js-yaml: 3.13.1 + vscode-jsonrpc: 3.6.2 + dev: false + resolution: + integrity: sha512-3DdIcHWXwVaX1otoNS38xLIUhjcyy/7jWwDMulAfAQ0PXp6H98uoUxVVsjz42FFalH6mm0K5Wwn1kx0Izx0Nlg== + /@azure-tools/codegen-csharp/3.0.262: + dependencies: + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-hNEmbvlEY87AmmVoDRyYEZDG4iHwfYx6G9B7M8n0JvdwyOHn/gb4qUb1ULaPmbFWxMnVFzW070ab61/1VpYVog== + /@azure-tools/codegen/2.5.290: + dependencies: + '@azure-tools/async-io': 3.0.252 + '@azure-tools/linq': 3.1.261 + js-yaml: 3.13.1 + semver: 5.7.1 + dev: false + resolution: + integrity: sha512-D9TuBY9YE+CE/EpbMaB3oVJq1xp7koIAQGlFrRNTLPgKNMelqkWK8HLnYSk810HL0rJFQjJE/BLx5lQsOjMYRQ== + /@azure-tools/codemodel-v3/3.1.264: + dependencies: + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-Zh/as7gux7ifD3J7JUHwRW/e7DrG7rSJBpIyysGZEHbhErxsiPeLTZsS5pDpzwXD3CsEA2hDxrNSDFpVNXNqog== + /@azure-tools/codemodel/4.13.348: + dependencies: + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/linq': 3.1.261 + dev: false + resolution: + integrity: sha512-/5tjloDiPLNdqBdNN1PHudqMQlgCb+8o6L/8Pd3nYHc20cnbg3y3c23N5xpsGqmwwhJhCRrrW2XKrJeP55i09Q== + /@azure-tools/linq/3.1.261: + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-SRYWE2SUYXBdqGoQYjBvvFtZKHLaYvL4HJwDKOp5PA0OCm5f3gLNVsXSwgzLzh4CiYjt0vsRiQy5AB4p7b8Ogg== + /@azure-tools/tasks/3.0.252: + dev: false + engines: + node: '>=10.12.0' + resolution: + integrity: sha512-VF63L3nKogeXoChEcDHPUr325JFTvSM1qhw5yZ/VMwSvC5zp2Ri7MPEixK/mni4cQJnFMuqDp+6M1vkPh8ZRRA== + /@babel/code-frame/7.10.4: + dependencies: + '@babel/highlight': 7.10.4 + dev: false + resolution: + integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + /@babel/helper-validator-identifier/7.10.4: + dev: false + resolution: + integrity: sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + /@babel/highlight/7.10.4: + dependencies: + '@babel/helper-validator-identifier': 7.10.4 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: false + resolution: + integrity: sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + /@microsoft.azure/autorest.testserver/2.9.9: + dependencies: + azure-storage: 2.10.3 + body-parser: 1.19.0 + busboy: 0.3.1 + chalk: 3.0.0 + cookie-parser: 1.4.5 + cors: 2.8.5 + debug: 3.2.6 + express: 4.17.1 + morgan: 1.10.0 + pug: 2.0.4 + request: 2.88.2 + request-promise-native: 1.0.9_request@2.88.2 + serve-favicon: 2.5.0 + socket.io: 2.3.0 + socket.io-client: 2.3.1 + underscore: 1.11.0 + wiremock: 2.25.0 + xml2js: 0.4.23 + dev: false + hasBin: true + resolution: + integrity: sha512-XPdWxb4jgSPmKKWgLjCHDEE9+Lc1QMbZZ2dJEd+RtdlATI1HOaE4j72keP2wmMF0acTWN85fngd5EFPCgN4CeA== + /@types/babel-types/7.0.9: + dev: false + resolution: + integrity: sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA== + /@types/babylon/6.16.5: + dependencies: + '@types/babel-types': 7.0.9 + dev: false + resolution: + integrity: sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w== + /@types/eslint-visitor-keys/1.0.0: + dev: false + resolution: + integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + /@types/js-yaml/3.12.1: + dev: false + resolution: + integrity: sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA== + /@types/json-schema/7.0.6: + dev: false + resolution: + integrity: sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + /@types/mocha/5.2.5: + dev: false + resolution: + integrity: sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww== + /@types/node/12.7.2: + dev: false + resolution: + integrity: sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== + /@types/xmlbuilder/0.0.34: + dev: false + resolution: + integrity: sha512-yVsHfYqJblSEg3DvUhGndpCZBZz2GiGVmqMa04fbGro2xzxRj85Q7MQ4os+MaXmKcpCDD42MXuxUWfoUKTuVdQ== + /@typescript-eslint/eslint-plugin/2.0.0_b7c2671679a3bd4e1f52a3d3da16606f: + dependencies: + '@typescript-eslint/experimental-utils': 2.0.0_eslint@6.2.2 + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + eslint-utils: 1.4.3 + functional-red-black-tree: 1.0.1 + regexpp: 2.0.1 + tsutils: 3.17.1_typescript@3.7.5 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + '@typescript-eslint/parser': ^2.0.0-alpha.0 + eslint: ^5.0.0 || ^6.0.0 + typescript: '*' + resolution: + integrity: sha512-Mo45nxTTELODdl7CgpZKJISvLb+Fu64OOO2ZFc2x8sYSnUpFrBUW3H+H/ZGYmEkfnL6VkdtOSxgdt+Av79j0sA== + /@typescript-eslint/experimental-utils/2.0.0_eslint@6.2.2: + dependencies: + '@types/json-schema': 7.0.6 + '@typescript-eslint/typescript-estree': 2.0.0 + eslint: 6.2.2 + eslint-scope: 4.0.3 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: '*' + resolution: + integrity: sha512-XGJG6GNBXIEx/mN4eTRypN/EUmsd0VhVGQ1AG+WTgdvjHl0G8vHhVBHrd/5oI6RRYBRnedNymSYWW1HAdivtmg== + /@typescript-eslint/parser/2.0.0_eslint@6.2.2: + dependencies: + '@types/eslint-visitor-keys': 1.0.0 + '@typescript-eslint/experimental-utils': 2.0.0_eslint@6.2.2 + '@typescript-eslint/typescript-estree': 2.0.0 + eslint: 6.2.2 + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 + resolution: + integrity: sha512-ibyMBMr0383ZKserIsp67+WnNVoM402HKkxqXGlxEZsXtnGGurbnY90pBO3e0nBUM7chEEOcxUhgw9aPq7fEBA== + /@typescript-eslint/typescript-estree/2.0.0: + dependencies: + lodash.unescape: 4.0.1 + semver: 6.3.0 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + resolution: + integrity: sha512-NXbmzA3vWrSgavymlzMWNecgNOuiMMp62MO3kI7awZRLRcsA1QrYWo6q08m++uuAGVbXH/prZi2y1AWuhSu63w== + /accepts/1.3.7: + dependencies: + mime-types: 2.1.27 + negotiator: 0.6.2 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + /acorn-globals/3.1.0: + dependencies: + acorn: 4.0.13 + dev: false + resolution: + integrity: sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= + /acorn-jsx/5.3.1_acorn@7.4.1: + dependencies: + acorn: 7.4.1 + dev: false + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + resolution: + integrity: sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + /acorn/3.3.0: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha1-ReN/s56No/JbruP/U2niu18iAXo= + /acorn/4.0.13: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + /acorn/7.4.1: + dev: false + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + /after/0.8.2: + dev: false + resolution: + integrity: sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + /ajv/6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.0 + dev: false + resolution: + integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + /align-text/0.1.4: + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= + /ansi-escapes/3.2.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + /ansi-regex/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + /ansi-regex/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + /ansi-regex/4.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + /ansi-styles/3.2.1: + dependencies: + color-convert: 1.9.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + /ansi-styles/4.3.0: + dependencies: + color-convert: 2.0.1 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + /argparse/1.0.10: + dependencies: + sprintf-js: 1.0.3 + dev: false + resolution: + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + /array-flatten/1.1.1: + dev: false + resolution: + integrity: sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + /arraybuffer.slice/0.0.7: + dev: false + resolution: + integrity: sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== + /asap/2.0.6: + dev: false + resolution: + integrity: sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + /asn1/0.2.4: + dependencies: + safer-buffer: 2.1.2 + dev: false + resolution: + integrity: sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + /assert-plus/1.0.0: + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + /astral-regex/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + /async-limiter/1.0.1: + dev: false + resolution: + integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + /asynckit/0.4.0: + dev: false + resolution: + integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k= + /aws-sign2/0.7.0: + dev: false + resolution: + integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + /aws4/1.10.1: + dev: false + resolution: + integrity: sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== + /azure-storage/2.10.3: + dependencies: + browserify-mime: 1.2.9 + extend: 3.0.2 + json-edm-parser: 0.1.2 + md5.js: 1.3.4 + readable-stream: 2.0.6 + request: 2.88.2 + underscore: 1.8.3 + uuid: 3.4.0 + validator: 9.4.1 + xml2js: 0.2.8 + xmlbuilder: 9.0.7 + dev: false + engines: + node: '>= 0.8.26' + resolution: + integrity: sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ== + /babel-runtime/6.26.0: + dependencies: + core-js: 2.6.11 + regenerator-runtime: 0.11.1 + dev: false + resolution: + integrity: sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + /babel-types/6.26.0: + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.17.20 + to-fast-properties: 1.0.3 + dev: false + resolution: + integrity: sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + /babylon/6.18.0: + dev: false + hasBin: true + resolution: + integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + /backo2/1.0.2: + dev: false + resolution: + integrity: sha1-MasayLEpNjRj41s+u2n038+6eUc= + /balanced-match/1.0.0: + dev: false + resolution: + integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + /base64-arraybuffer/0.1.4: + dev: false + engines: + node: '>= 0.6.0' + resolution: + integrity: sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + /base64-arraybuffer/0.1.5: + dev: false + engines: + node: '>= 0.6.0' + resolution: + integrity: sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + /base64id/2.0.0: + dev: false + engines: + node: ^4.5.0 || >= 5.9 + resolution: + integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + /basic-auth/2.0.1: + dependencies: + safe-buffer: 5.1.2 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + /bcrypt-pbkdf/1.0.2: + dependencies: + tweetnacl: 0.14.5 + dev: false + resolution: + integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + /better-assert/1.0.2: + dependencies: + callsite: 1.0.0 + dev: false + resolution: + integrity: sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + /blob/0.0.5: + dev: false + resolution: + integrity: sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== + /body-parser/1.19.0: + dependencies: + bytes: 3.1.0 + content-type: 1.0.4 + debug: 2.6.9 + depd: 1.1.2 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.7.0 + raw-body: 2.4.0 + type-is: 1.6.18 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + /brace-expansion/1.1.11: + dependencies: + balanced-match: 1.0.0 + concat-map: 0.0.1 + dev: false + resolution: + integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + /browser-stdout/1.3.1: + dev: false + resolution: + integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + /browserify-mime/1.2.9: + dev: false + resolution: + integrity: sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8= + /buffer-from/1.1.1: + dev: false + resolution: + integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + /busboy/0.3.1: + dependencies: + dicer: 0.3.0 + dev: false + engines: + node: '>=4.5.0' + resolution: + integrity: sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw== + /bytes/3.1.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + /callsite/1.0.0: + dev: false + resolution: + integrity: sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + /callsites/3.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + /camelcase/1.2.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + /camelcase/4.1.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + /caseless/0.12.0: + dev: false + resolution: + integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + /center-align/0.1.3: + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qg0yYptu6XIgBBHL1EYckHvCt60= + /chalk/2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + /chalk/3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + /character-parser/2.2.0: + dependencies: + is-regex: 1.1.1 + dev: false + resolution: + integrity: sha1-x84o821LzZdE5f/CxfzeHHMmH8A= + /chardet/0.7.0: + dev: false + resolution: + integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + /clean-css/4.2.3: + dependencies: + source-map: 0.6.1 + dev: false + engines: + node: '>= 4.0' + resolution: + integrity: sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== + /cli-cursor/2.1.0: + dependencies: + restore-cursor: 2.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + /cli-width/2.2.1: + dev: false + resolution: + integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + /cliui/2.1.0: + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: false + resolution: + integrity: sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= + /cliui/4.1.0: + dependencies: + string-width: 2.1.1 + strip-ansi: 4.0.0 + wrap-ansi: 2.1.0 + dev: false + resolution: + integrity: sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + /code-point-at/1.1.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + /color-convert/1.9.3: + dependencies: + color-name: 1.1.3 + dev: false + resolution: + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + /color-convert/2.0.1: + dependencies: + color-name: 1.1.4 + dev: false + engines: + node: '>=7.0.0' + resolution: + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + /color-name/1.1.3: + dev: false + resolution: + integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + /color-name/1.1.4: + dev: false + resolution: + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + /combined-stream/1.0.8: + dependencies: + delayed-stream: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + /commander/2.15.1: + dev: false + resolution: + integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + /component-bind/1.0.0: + dev: false + resolution: + integrity: sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + /component-emitter/1.2.1: + dev: false + resolution: + integrity: sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + /component-emitter/1.3.0: + dev: false + resolution: + integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + /component-inherit/0.0.3: + dev: false + resolution: + integrity: sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + /concat-map/0.0.1: + dev: false + resolution: + integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + /constantinople/3.1.2: + dependencies: + '@types/babel-types': 7.0.9 + '@types/babylon': 6.16.5 + babel-types: 6.26.0 + babylon: 6.18.0 + dev: false + resolution: + integrity: sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw== + /content-disposition/0.5.3: + dependencies: + safe-buffer: 5.1.2 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + /content-type/1.0.4: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + /cookie-parser/1.4.5: + dependencies: + cookie: 0.4.0 + cookie-signature: 1.0.6 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw== + /cookie-signature/1.0.6: + dev: false + resolution: + integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + /cookie/0.3.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + /cookie/0.4.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + /core-js/2.6.11: + deprecated: 'core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.' + dev: false + requiresBuild: true + resolution: + integrity: sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + /core-util-is/1.0.2: + dev: false + resolution: + integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + /cors/2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + /cross-spawn/6.0.5: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: false + engines: + node: '>=4.8' + resolution: + integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + /dashdash/1.14.1: + dependencies: + assert-plus: 1.0.0 + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + /debug/2.6.9: + dependencies: + ms: 2.0.0 + dev: false + resolution: + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + /debug/3.1.0: + dependencies: + ms: 2.0.0 + dev: false + resolution: + integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + /debug/3.2.6: + dependencies: + ms: 2.1.2 + dev: false + resolution: + integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + /debug/4.1.1: + dependencies: + ms: 2.1.2 + dev: false + resolution: + integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + /debug/4.2.0: + dependencies: + ms: 2.1.2 + dev: false + engines: + node: '>=6.0' + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + resolution: + integrity: sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + /decamelize/1.2.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + /deep-is/0.1.3: + dev: false + resolution: + integrity: sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + /delayed-stream/1.0.0: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + /depd/1.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + /depd/2.0.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + /destroy/1.0.4: + dev: false + resolution: + integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + /dicer/0.3.0: + dependencies: + streamsearch: 0.1.2 + dev: false + engines: + node: '>=4.5.0' + resolution: + integrity: sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== + /diff/3.5.0: + dev: false + engines: + node: '>=0.3.1' + resolution: + integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + /doctrine/3.0.0: + dependencies: + esutils: 2.0.3 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + /doctypes/1.1.0: + dev: false + resolution: + integrity: sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= + /ecc-jsbn/0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: false + resolution: + integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + /ee-first/1.1.1: + dev: false + resolution: + integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + /emoji-regex/7.0.3: + dev: false + resolution: + integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + /encodeurl/1.0.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + /end-of-stream/1.4.4: + dependencies: + once: 1.4.0 + dev: false + resolution: + integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + /engine.io-client/3.4.4: + dependencies: + component-emitter: 1.3.0 + component-inherit: 0.0.3 + debug: 3.1.0 + engine.io-parser: 2.2.1 + has-cors: 1.1.0 + indexof: 0.0.1 + parseqs: 0.0.6 + parseuri: 0.0.6 + ws: 6.1.4 + xmlhttprequest-ssl: 1.5.5 + yeast: 0.1.2 + dev: false + resolution: + integrity: sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ== + /engine.io-parser/2.2.1: + dependencies: + after: 0.8.2 + arraybuffer.slice: 0.0.7 + base64-arraybuffer: 0.1.4 + blob: 0.0.5 + has-binary2: 1.0.3 + dev: false + resolution: + integrity: sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== + /engine.io/3.4.2: + dependencies: + accepts: 1.3.7 + base64id: 2.0.0 + cookie: 0.3.1 + debug: 4.1.1 + engine.io-parser: 2.2.1 + ws: 7.3.1 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg== + /escape-html/1.0.3: + dev: false + resolution: + integrity: sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + /escape-string-regexp/1.0.5: + dev: false + engines: + node: '>=0.8.0' + resolution: + integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + /eslint-scope/4.0.3: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + /eslint-scope/5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + /eslint-utils/1.4.3: + dependencies: + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + /eslint-visitor-keys/1.3.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + /eslint/6.2.2: + dependencies: + '@babel/code-frame': 7.10.4 + ajv: 6.12.6 + chalk: 2.4.2 + cross-spawn: 6.0.5 + debug: 4.2.0 + doctrine: 3.0.0 + eslint-scope: 5.1.1 + eslint-utils: 1.4.3 + eslint-visitor-keys: 1.3.0 + espree: 6.2.1 + esquery: 1.3.1 + esutils: 2.0.3 + file-entry-cache: 5.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.1 + globals: 11.12.0 + ignore: 4.0.6 + import-fresh: 3.2.1 + imurmurhash: 0.1.4 + inquirer: 6.5.2 + is-glob: 4.0.1 + js-yaml: 3.13.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.3.0 + lodash: 4.17.20 + minimatch: 3.0.4 + mkdirp: 0.5.5 + natural-compare: 1.4.0 + optionator: 0.8.3 + progress: 2.0.3 + regexpp: 2.0.1 + semver: 6.3.0 + strip-ansi: 5.2.0 + strip-json-comments: 3.1.1 + table: 5.4.6 + text-table: 0.2.0 + v8-compile-cache: 2.1.1 + dev: false + engines: + node: ^8.10.0 || ^10.13.0 || >=11.10.1 + hasBin: true + resolution: + integrity: sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw== + /espree/6.2.1: + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.1_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== + /esprima/4.0.1: + dev: false + engines: + node: '>=4' + hasBin: true + resolution: + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + /esquery/1.3.1: + dependencies: + estraverse: 5.2.0 + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + /esrecurse/4.3.0: + dependencies: + estraverse: 5.2.0 + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + /estraverse/4.3.0: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + /estraverse/5.2.0: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + /esutils/2.0.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + /etag/1.8.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + /execa/1.0.0: + dependencies: + cross-spawn: 6.0.5 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.3 + strip-eof: 1.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + /express/4.17.1: + dependencies: + accepts: 1.3.7 + array-flatten: 1.1.1 + body-parser: 1.19.0 + content-disposition: 0.5.3 + content-type: 1.0.4 + cookie: 0.4.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.6 + qs: 6.7.0 + range-parser: 1.2.1 + safe-buffer: 5.1.2 + send: 0.17.1 + serve-static: 1.14.1 + setprototypeof: 1.1.1 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + dev: false + engines: + node: '>= 0.10.0' + resolution: + integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + /extend/3.0.2: + dev: false + resolution: + integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + /external-editor/3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + /extsprintf/1.3.0: + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + /fast-deep-equal/3.1.3: + dev: false + resolution: + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + /fast-json-stable-stringify/2.1.0: + dev: false + resolution: + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + /fast-levenshtein/2.0.6: + dev: false + resolution: + integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + /figures/2.0.0: + dependencies: + escape-string-regexp: 1.0.5 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + /file-entry-cache/5.0.1: + dependencies: + flat-cache: 2.0.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + /finalhandler/1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + /find-up/2.1.0: + dependencies: + locate-path: 2.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + /flat-cache/2.0.1: + dependencies: + flatted: 2.0.2 + rimraf: 2.6.3 + write: 1.0.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + /flatted/2.0.2: + dev: false + resolution: + integrity: sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + /forever-agent/0.6.1: + dev: false + resolution: + integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + /form-data/2.3.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.27 + dev: false + engines: + node: '>= 0.12' + resolution: + integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + /forwarded/0.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + /fresh/0.5.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + /fs.realpath/1.0.0: + dev: false + resolution: + integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + /functional-red-black-tree/1.0.1: + dev: false + resolution: + integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + /get-caller-file/1.0.3: + dev: false + resolution: + integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + /get-stream/4.1.0: + dependencies: + pump: 3.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + /getpass/0.1.7: + dependencies: + assert-plus: 1.0.0 + dev: false + resolution: + integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + /glob-parent/5.1.1: + dependencies: + is-glob: 4.0.1 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + /glob/7.1.2: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + resolution: + integrity: sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + /glob/7.1.6: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + resolution: + integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + /globals/11.12.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + /graceful-fs/4.2.4: + dev: false + resolution: + integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + /growl/1.10.5: + dev: false + engines: + node: '>=4.x' + resolution: + integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + /har-schema/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + /har-validator/5.1.5: + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + deprecated: this library is no longer supported + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + /has-binary2/1.0.3: + dependencies: + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== + /has-cors/1.1.0: + dev: false + resolution: + integrity: sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + /has-flag/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + /has-flag/4.0.0: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + /has-symbols/1.0.1: + dev: false + engines: + node: '>= 0.4' + resolution: + integrity: sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + /hash-base/3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.0 + safe-buffer: 5.2.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + /he/1.1.1: + dev: false + hasBin: true + resolution: + integrity: sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + /http-errors/1.7.2: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + /http-errors/1.7.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + /http-signature/1.2.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.1 + sshpk: 1.16.1 + dev: false + engines: + node: '>=0.8' + npm: '>=1.3.7' + resolution: + integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + /iconv-lite/0.4.24: + dependencies: + safer-buffer: 2.1.2 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + /ignore/4.0.6: + dev: false + engines: + node: '>= 4' + resolution: + integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + /import-fresh/3.2.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + /imurmurhash/0.1.4: + dev: false + engines: + node: '>=0.8.19' + resolution: + integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o= + /indexof/0.0.1: + dev: false + resolution: + integrity: sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + /inflight/1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + resolution: + integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + /inherits/2.0.3: + dev: false + resolution: + integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + /inherits/2.0.4: + dev: false + resolution: + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + /inquirer/6.5.2: + dependencies: + ansi-escapes: 3.2.0 + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-width: 2.2.1 + external-editor: 3.1.0 + figures: 2.0.0 + lodash: 4.17.20 + mute-stream: 0.0.7 + run-async: 2.4.1 + rxjs: 6.6.3 + string-width: 2.1.1 + strip-ansi: 5.2.0 + through: 2.3.8 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + /interpret/1.4.0: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + /invert-kv/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + /ipaddr.js/1.9.1: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + /is-buffer/1.1.6: + dev: false + resolution: + integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + /is-expression/3.0.0: + dependencies: + acorn: 4.0.13 + object-assign: 4.1.1 + dev: false + resolution: + integrity: sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8= + /is-extglob/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + /is-fullwidth-code-point/1.0.0: + dependencies: + number-is-nan: 1.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + /is-fullwidth-code-point/2.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + /is-glob/4.0.1: + dependencies: + is-extglob: 2.1.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + /is-promise/2.2.2: + dev: false + resolution: + integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + /is-regex/1.1.1: + dependencies: + has-symbols: 1.0.1 + dev: false + engines: + node: '>= 0.4' + resolution: + integrity: sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + /is-stream/1.1.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + /is-typedarray/1.0.0: + dev: false + resolution: + integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + /isarray/1.0.0: + dev: false + resolution: + integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + /isarray/2.0.1: + dev: false + resolution: + integrity: sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + /isexe/2.0.0: + dev: false + resolution: + integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + /isstream/0.1.2: + dev: false + resolution: + integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + /js-stringify/1.0.2: + dev: false + resolution: + integrity: sha1-Fzb939lyTyijaCrcYjCufk6Weds= + /js-tokens/4.0.0: + dev: false + resolution: + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + /js-yaml/3.13.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + hasBin: true + resolution: + integrity: sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + /jsbn/0.1.1: + dev: false + resolution: + integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + /json-edm-parser/0.1.2: + dependencies: + jsonparse: 1.2.0 + dev: false + resolution: + integrity: sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ= + /json-schema-traverse/0.4.1: + dev: false + resolution: + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + /json-schema/0.2.3: + dev: false + resolution: + integrity: sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + /json-stable-stringify-without-jsonify/1.0.1: + dev: false + resolution: + integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + /json-stringify-safe/5.0.1: + dev: false + resolution: + integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + /jsonparse/1.2.0: + dev: false + engines: + '0': node >= 0.2.0 + resolution: + integrity: sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70= + /jsprim/1.4.1: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.2.3 + verror: 1.10.0 + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + /jstransformer/1.0.0: + dependencies: + is-promise: 2.2.2 + promise: 7.3.1 + dev: false + resolution: + integrity: sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= + /kind-of/3.2.2: + dependencies: + is-buffer: 1.1.6 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + /lazy-cache/1.0.4: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-odePw6UEdMuAhF07O24dpJpEbo4= + /lcid/2.0.0: + dependencies: + invert-kv: 2.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + /levn/0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + /locate-path/2.0.0: + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + /lodash.unescape/4.0.1: + dev: false + resolution: + integrity: sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + /lodash/4.17.20: + dev: false + resolution: + integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + /longest/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + /map-age-cleaner/0.1.3: + dependencies: + p-defer: 1.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + /md5.js/1.3.4: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: false + resolution: + integrity: sha1-6b296UogpawYsENA/Fdk1bCdkB0= + /media-typer/0.3.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + /mem/4.3.0: + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 2.1.0 + p-is-promise: 2.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + /merge-descriptors/1.0.1: + dev: false + resolution: + integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + /methods/1.1.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + /mime-db/1.44.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + /mime-types/2.1.27: + dependencies: + mime-db: 1.44.0 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + /mime/1.6.0: + dev: false + engines: + node: '>=4' + hasBin: true + resolution: + integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + /mimic-fn/1.2.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + /mimic-fn/2.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + /minimatch/3.0.4: + dependencies: + brace-expansion: 1.1.11 + dev: false + resolution: + integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + /minimist/0.0.8: + dev: false + resolution: + integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + /minimist/1.2.5: + dev: false + resolution: + integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + /mkdirp/0.5.1: + dependencies: + minimist: 0.0.8 + deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) + dev: false + hasBin: true + resolution: + integrity: sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + /mkdirp/0.5.5: + dependencies: + minimist: 1.2.5 + dev: false + hasBin: true + resolution: + integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + /mocha-typescript/1.1.17: + dependencies: + '@types/mocha': 5.2.5 + chalk: 2.4.2 + cross-spawn: 6.0.5 + yargs: 11.1.1 + deprecated: 'mocha-typescript has been deprecated, use @testdeck/mocha instead' + dev: false + hasBin: true + resolution: + integrity: sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA== + /mocha/5.2.0: + dependencies: + browser-stdout: 1.3.1 + commander: 2.15.1 + debug: 3.1.0 + diff: 3.5.0 + escape-string-regexp: 1.0.5 + glob: 7.1.2 + growl: 1.10.5 + he: 1.1.1 + minimatch: 3.0.4 + mkdirp: 0.5.1 + supports-color: 5.4.0 + dev: false + engines: + node: '>= 4.0.0' + hasBin: true + resolution: + integrity: sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + /morgan/1.10.0: + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.0.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + /ms/2.0.0: + dev: false + resolution: + integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + /ms/2.1.1: + dev: false + resolution: + integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + /ms/2.1.2: + dev: false + resolution: + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + /mute-stream/0.0.7: + dev: false + resolution: + integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + /natural-compare/1.4.0: + dev: false + resolution: + integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + /negotiator/0.6.2: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + /nice-try/1.0.5: + dev: false + resolution: + integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + /npm-run-path/2.0.2: + dependencies: + path-key: 2.0.1 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + /number-is-nan/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + /oauth-sign/0.9.0: + dev: false + resolution: + integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + /object-assign/4.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + /object-component/0.0.3: + dev: false + resolution: + integrity: sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + /on-finished/2.3.0: + dependencies: + ee-first: 1.1.1 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + /on-headers/1.0.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + /once/1.4.0: + dependencies: + wrappy: 1.0.2 + dev: false + resolution: + integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + /onetime/2.0.1: + dependencies: + mimic-fn: 1.2.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + /optionator/0.8.3: + dependencies: + deep-is: 0.1.3 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.3 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + /os-locale/3.1.0: + dependencies: + execa: 1.0.0 + lcid: 2.0.0 + mem: 4.3.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + /os-tmpdir/1.0.2: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + /p-defer/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + /p-finally/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + /p-is-promise/2.1.0: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + /p-limit/1.3.0: + dependencies: + p-try: 1.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + /p-locate/2.0.0: + dependencies: + p-limit: 1.3.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + /p-try/1.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + /parent-module/1.0.1: + dependencies: + callsites: 3.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + /parseqs/0.0.5: + dependencies: + better-assert: 1.0.2 + dev: false + resolution: + integrity: sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + /parseqs/0.0.6: + dev: false + resolution: + integrity: sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== + /parseuri/0.0.5: + dependencies: + better-assert: 1.0.2 + dev: false + resolution: + integrity: sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + /parseuri/0.0.6: + dev: false + resolution: + integrity: sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== + /parseurl/1.3.3: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + /path-exists/3.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + /path-is-absolute/1.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + /path-key/2.0.1: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + /path-parse/1.0.6: + dev: false + resolution: + integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + /path-to-regexp/0.1.7: + dev: false + resolution: + integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + /performance-now/2.1.0: + dev: false + resolution: + integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + /prelude-ls/1.1.2: + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + /process-nextick-args/1.0.7: + dev: false + resolution: + integrity: sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= + /progress/2.0.3: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + /promise/7.3.1: + dependencies: + asap: 2.0.6 + dev: false + resolution: + integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + /proper-lockfile/2.0.1: + dependencies: + graceful-fs: 4.2.4 + retry: 0.10.1 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0= + /proxy-addr/2.0.6: + dependencies: + forwarded: 0.1.2 + ipaddr.js: 1.9.1 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + /psl/1.8.0: + dev: false + resolution: + integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + /pug-attrs/2.0.4: + dependencies: + constantinople: 3.1.2 + js-stringify: 1.0.2 + pug-runtime: 2.0.5 + dev: false + resolution: + integrity: sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ== + /pug-code-gen/2.0.2: + dependencies: + constantinople: 3.1.2 + doctypes: 1.1.0 + js-stringify: 1.0.2 + pug-attrs: 2.0.4 + pug-error: 1.3.3 + pug-runtime: 2.0.5 + void-elements: 2.0.1 + with: 5.1.1 + dev: false + resolution: + integrity: sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw== + /pug-error/1.3.3: + dev: false + resolution: + integrity: sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ== + /pug-filters/3.1.1: + dependencies: + clean-css: 4.2.3 + constantinople: 3.1.2 + jstransformer: 1.0.0 + pug-error: 1.3.3 + pug-walk: 1.1.8 + resolve: 1.17.0 + uglify-js: 2.8.29 + dev: false + resolution: + integrity: sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg== + /pug-lexer/4.1.0: + dependencies: + character-parser: 2.2.0 + is-expression: 3.0.0 + pug-error: 1.3.3 + dev: false + resolution: + integrity: sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA== + /pug-linker/3.0.6: + dependencies: + pug-error: 1.3.3 + pug-walk: 1.1.8 + dev: false + resolution: + integrity: sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg== + /pug-load/2.0.12: + dependencies: + object-assign: 4.1.1 + pug-walk: 1.1.8 + dev: false + resolution: + integrity: sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg== + /pug-parser/5.0.1: + dependencies: + pug-error: 1.3.3 + token-stream: 0.0.1 + dev: false + resolution: + integrity: sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA== + /pug-runtime/2.0.5: + dev: false + resolution: + integrity: sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw== + /pug-strip-comments/1.0.4: + dependencies: + pug-error: 1.3.3 + dev: false + resolution: + integrity: sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw== + /pug-walk/1.1.8: + dev: false + resolution: + integrity: sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA== + /pug/2.0.4: + dependencies: + pug-code-gen: 2.0.2 + pug-filters: 3.1.1 + pug-lexer: 4.1.0 + pug-linker: 3.0.6 + pug-load: 2.0.12 + pug-parser: 5.0.1 + pug-runtime: 2.0.5 + pug-strip-comments: 1.0.4 + dev: false + resolution: + integrity: sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw== + /pump/3.0.0: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + resolution: + integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + /punycode/2.1.1: + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + /qs/6.5.2: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + /qs/6.7.0: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + /range-parser/1.2.1: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + /raw-body/2.4.0: + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + /readable-stream/2.0.6: + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 1.0.7 + string_decoder: 0.10.31 + util-deprecate: 1.0.2 + dev: false + resolution: + integrity: sha1-j5A0HmilPMySh4jaz80Rs265t44= + /readable-stream/3.6.0: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + /rechoir/0.6.2: + dependencies: + resolve: 1.17.0 + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + /regenerator-runtime/0.11.1: + dev: false + resolution: + integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + /regexpp/2.0.1: + dev: false + engines: + node: '>=6.5.0' + resolution: + integrity: sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + /repeat-string/1.6.1: + dev: false + engines: + node: '>=0.10' + resolution: + integrity: sha1-jcrkcOHIirwtYA//Sndihtp15jc= + /request-promise-core/1.1.4_request@2.88.2: + dependencies: + lodash: 4.17.20 + request: 2.88.2 + dev: false + engines: + node: '>=0.10.0' + peerDependencies: + request: ^2.34 + resolution: + integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + /request-promise-native/1.0.9_request@2.88.2: + dependencies: + request: 2.88.2 + request-promise-core: 1.1.4_request@2.88.2 + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + deprecated: 'request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142' + dev: false + engines: + node: '>=0.12.0' + peerDependencies: + request: ^2.34 + resolution: + integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + /request/2.88.2: + dependencies: + aws-sign2: 0.7.0 + aws4: 1.10.1 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.27 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.2 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + deprecated: 'request has been deprecated, see https://github.com/request/request/issues/3142' + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + /require-directory/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + /require-main-filename/1.0.1: + dev: false + resolution: + integrity: sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + /resolve-from/4.0.0: + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + /resolve/1.17.0: + dependencies: + path-parse: 1.0.6 + dev: false + resolution: + integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + /restore-cursor/2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.3 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + /retry/0.10.1: + dev: false + resolution: + integrity: sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + /right-align/0.1.3: + dependencies: + align-text: 0.1.4 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + /rimraf/2.6.3: + dependencies: + glob: 7.1.6 + dev: false + hasBin: true + resolution: + integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + /run-async/2.4.1: + dev: false + engines: + node: '>=0.12.0' + resolution: + integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + /rxjs/6.6.3: + dependencies: + tslib: 1.14.1 + dev: false + engines: + npm: '>=2.0.0' + resolution: + integrity: sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== + /safe-buffer/5.1.1: + dev: false + resolution: + integrity: sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== + /safe-buffer/5.1.2: + dev: false + resolution: + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + /safe-buffer/5.2.1: + dev: false + resolution: + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + /safer-buffer/2.1.2: + dev: false + resolution: + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + /sax/0.5.8: + dev: false + resolution: + integrity: sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE= + /sax/1.2.4: + dev: false + resolution: + integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + /semver/5.7.1: + dev: false + hasBin: true + resolution: + integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + /semver/6.3.0: + dev: false + hasBin: true + resolution: + integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + /send/0.17.1: + dependencies: + debug: 2.6.9 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.7.3 + mime: 1.6.0 + ms: 2.1.1 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + /serve-favicon/2.5.0: + dependencies: + etag: 1.8.1 + fresh: 0.5.2 + ms: 2.1.1 + parseurl: 1.3.3 + safe-buffer: 5.1.1 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-k10kDN/g9YBTB/3+ln2IlCosvPA= + /serve-static/1.14.1: + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.1 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + /set-blocking/2.0.0: + dev: false + resolution: + integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + /setprototypeof/1.1.1: + dev: false + resolution: + integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + /shebang-command/1.2.0: + dependencies: + shebang-regex: 1.0.0 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + /shebang-regex/1.0.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + /shelljs/0.7.8: + dependencies: + glob: 7.1.6 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: false + engines: + node: '>=0.11.0' + hasBin: true + resolution: + integrity: sha1-3svPh0sNHl+3LhSxZKloMEjprLM= + /signal-exit/3.0.3: + dev: false + resolution: + integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + /slice-ansi/2.1.0: + dependencies: + ansi-styles: 3.2.1 + astral-regex: 1.0.0 + is-fullwidth-code-point: 2.0.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + /socket.io-adapter/1.1.2: + dev: false + resolution: + integrity: sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== + /socket.io-client/2.3.0: + dependencies: + backo2: 1.0.2 + base64-arraybuffer: 0.1.5 + component-bind: 1.0.0 + component-emitter: 1.2.1 + debug: 4.1.1 + engine.io-client: 3.4.4 + has-binary2: 1.0.3 + has-cors: 1.1.0 + indexof: 0.0.1 + object-component: 0.0.3 + parseqs: 0.0.5 + parseuri: 0.0.5 + socket.io-parser: 3.3.1 + to-array: 0.1.4 + dev: false + resolution: + integrity: sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== + /socket.io-client/2.3.1: + dependencies: + backo2: 1.0.2 + component-bind: 1.0.0 + component-emitter: 1.3.0 + debug: 3.1.0 + engine.io-client: 3.4.4 + has-binary2: 1.0.3 + indexof: 0.0.1 + parseqs: 0.0.6 + parseuri: 0.0.6 + socket.io-parser: 3.3.1 + to-array: 0.1.4 + dev: false + resolution: + integrity: sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ== + /socket.io-parser/3.3.1: + dependencies: + component-emitter: 1.3.0 + debug: 3.1.0 + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ== + /socket.io-parser/3.4.1: + dependencies: + component-emitter: 1.2.1 + debug: 4.1.1 + isarray: 2.0.1 + dev: false + resolution: + integrity: sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A== + /socket.io/2.3.0: + dependencies: + debug: 4.1.1 + engine.io: 3.4.2 + has-binary2: 1.0.3 + socket.io-adapter: 1.1.2 + socket.io-client: 2.3.0 + socket.io-parser: 3.4.1 + dev: false + resolution: + integrity: sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg== + /source-map-support/0.5.13: + dependencies: + buffer-from: 1.1.1 + source-map: 0.6.1 + dev: false + resolution: + integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + /source-map/0.5.7: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + /source-map/0.6.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + /sprintf-js/1.0.3: + dev: false + resolution: + integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + /sshpk/1.16.1: + dependencies: + asn1: 0.2.4 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: false + engines: + node: '>=0.10.0' + hasBin: true + resolution: + integrity: sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + /statuses/1.5.0: + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + /stealthy-require/1.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + /streamsearch/0.1.2: + dev: false + engines: + node: '>=0.8.0' + resolution: + integrity: sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= + /string-width/1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + /string-width/2.1.1: + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + /string-width/3.1.0: + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + /string_decoder/0.10.31: + dev: false + resolution: + integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + /string_decoder/1.3.0: + dependencies: + safe-buffer: 5.2.1 + dev: false + resolution: + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + /strip-ansi/3.0.1: + dependencies: + ansi-regex: 2.1.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + /strip-ansi/4.0.0: + dependencies: + ansi-regex: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha1-qEeQIusaw2iocTibY1JixQXuNo8= + /strip-ansi/5.2.0: + dependencies: + ansi-regex: 4.1.0 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + /strip-eof/1.0.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + /strip-json-comments/3.1.1: + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + /supports-color/5.4.0: + dependencies: + has-flag: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + /supports-color/5.5.0: + dependencies: + has-flag: 3.0.0 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + /supports-color/7.2.0: + dependencies: + has-flag: 4.0.0 + dev: false + engines: + node: '>=8' + resolution: + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + /table/5.4.6: + dependencies: + ajv: 6.12.6 + lodash: 4.17.20 + slice-ansi: 2.1.0 + string-width: 3.1.0 + dev: false + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + /text-table/0.2.0: + dev: false + resolution: + integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + /through/2.3.8: + dev: false + resolution: + integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + /tmp/0.0.33: + dependencies: + os-tmpdir: 1.0.2 + dev: false + engines: + node: '>=0.6.0' + resolution: + integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + /to-array/0.1.4: + dev: false + resolution: + integrity: sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + /to-fast-properties/1.0.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + /toidentifier/1.0.0: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + /token-stream/0.0.1: + dev: false + resolution: + integrity: sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= + /tough-cookie/2.5.0: + dependencies: + psl: 1.8.0 + punycode: 2.1.1 + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + /tslib/1.14.1: + dev: false + resolution: + integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + /tsutils/3.17.1_typescript@3.7.5: + dependencies: + tslib: 1.14.1 + typescript: 3.7.5 + dev: false + engines: + node: '>= 6' + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + resolution: + integrity: sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + /tunnel-agent/0.6.0: + dependencies: + safe-buffer: 5.2.1 + dev: false + resolution: + integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + /tweetnacl/0.14.5: + dev: false + resolution: + integrity: sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + /type-check/0.3.2: + dependencies: + prelude-ls: 1.1.2 + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + /type-is/1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.27 + dev: false + engines: + node: '>= 0.6' + resolution: + integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + /typescript/3.7.5: + dev: false + engines: + node: '>=4.2.0' + hasBin: true + resolution: + integrity: sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + /uglify-js/2.8.29: + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + dev: false + engines: + node: '>=0.8.0' + hasBin: true + optionalDependencies: + uglify-to-browserify: 1.0.2 + resolution: + integrity: sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + /uglify-to-browserify/1.0.2: + dev: false + optional: true + resolution: + integrity: sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + /underscore/1.11.0: + dev: false + resolution: + integrity: sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw== + /underscore/1.8.3: + dev: false + resolution: + integrity: sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= + /unpipe/1.0.0: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + /uri-js/4.4.0: + dependencies: + punycode: 2.1.1 + dev: false + resolution: + integrity: sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + /util-deprecate/1.0.2: + dev: false + resolution: + integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + /utils-merge/1.0.1: + dev: false + engines: + node: '>= 0.4.0' + resolution: + integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + /uuid/3.4.0: + dev: false + hasBin: true + resolution: + integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + /v8-compile-cache/2.1.1: + dev: false + resolution: + integrity: sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + /validator/9.4.1: + dev: false + engines: + node: '>= 0.10' + resolution: + integrity: sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA== + /vary/1.1.2: + dev: false + engines: + node: '>= 0.8' + resolution: + integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + /verror/1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: false + engines: + '0': node >=0.6.0 + resolution: + integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + /void-elements/2.0.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + /vscode-jsonrpc/3.6.2: + dev: false + engines: + node: '>=4.0.0 || >=6.0.0' + resolution: + integrity: sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA== + /which-module/2.0.0: + dev: false + resolution: + integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + /which/1.3.1: + dependencies: + isexe: 2.0.0 + dev: false + hasBin: true + resolution: + integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + /window-size/0.1.0: + dev: false + engines: + node: '>= 0.8.0' + resolution: + integrity: sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + /wiremock/2.25.0: + dependencies: + shelljs: 0.7.8 + dev: false + hasBin: true + resolution: + integrity: sha512-F7i9ikOENfz7QnhvDFJGFFVkmSq3+wySLFiNLB5NAThRCw0xdU0FimkAHLP6MLEnqxvg1/O7JEaTg+PAaX24+w== + /with/5.1.1: + dependencies: + acorn: 3.3.0 + acorn-globals: 3.1.0 + dev: false + resolution: + integrity: sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4= + /word-wrap/1.2.3: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + /wordwrap/0.0.2: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + /wrap-ansi/2.1.0: + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + /wrappy/1.0.2: + dev: false + resolution: + integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + /write/1.0.3: + dependencies: + mkdirp: 0.5.5 + dev: false + engines: + node: '>=4' + resolution: + integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + /ws/6.1.4: + dependencies: + async-limiter: 1.0.1 + dev: false + resolution: + integrity: sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + /ws/7.3.1: + dev: false + engines: + node: '>=8.3.0' + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + resolution: + integrity: sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== + /xml2js/0.2.8: + dependencies: + sax: 0.5.8 + dev: false + resolution: + integrity: sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I= + /xml2js/0.4.23: + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 + dev: false + engines: + node: '>=4.0.0' + resolution: + integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + /xmlbuilder/10.1.1: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg== + /xmlbuilder/11.0.1: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + /xmlbuilder/9.0.7: + dev: false + engines: + node: '>=4.0' + resolution: + integrity: sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + /xmlhttprequest-ssl/1.5.5: + dev: false + engines: + node: '>=0.4.0' + resolution: + integrity: sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= + /y18n/3.2.1: + dev: false + resolution: + integrity: sha1-bRX7qITAhnnA136I53WegR4H+kE= + /yargs-parser/9.0.2: + dependencies: + camelcase: 4.1.0 + dev: false + resolution: + integrity: sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + /yargs/11.1.1: + dependencies: + cliui: 4.1.0 + decamelize: 1.2.0 + find-up: 2.1.0 + get-caller-file: 1.0.3 + os-locale: 3.1.0 + require-directory: 2.1.1 + require-main-filename: 1.0.1 + set-blocking: 2.0.0 + string-width: 2.1.1 + which-module: 2.0.0 + y18n: 3.2.1 + yargs-parser: 9.0.2 + dev: false + resolution: + integrity: sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== + /yargs/3.10.0: + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: false + resolution: + integrity: sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + /yeast/0.1.2: + dev: false + resolution: + integrity: sha1-AI4G2AlDIMNy28L47XagymyKxBk= + 'file:projects/powershell.tgz': + dependencies: + '@autorest/autorest': 3.0.6187 + '@azure-tools/async-io': 3.0.252 + '@azure-tools/autorest-extension-base': 3.1.266 + '@azure-tools/codegen': 2.5.290 + '@azure-tools/codegen-csharp': 3.0.262 + '@azure-tools/codemodel': 4.13.348 + '@azure-tools/codemodel-v3': 3.1.264 + '@azure-tools/linq': 3.1.261 + '@azure-tools/tasks': 3.0.252 + '@microsoft.azure/autorest.testserver': 2.9.9 + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': 2.0.0_b7c2671679a3bd4e1f52a3d3da16606f + '@typescript-eslint/parser': 2.0.0_eslint@6.2.2 + eslint: 6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: 3.7.5 + xmlbuilder: 10.1.1 + dev: false + name: '@rush-temp/powershell' + resolution: + integrity: sha512-p6zFKQmmQo1rntIeAg/ELKH+i12IV+ZcTM9J3luYZeV7zc1mZ3A+DReEuxshx+3oR0WyOCw9jUgTm0hGHJQXWA== + tarball: 'file:projects/powershell.tgz' + version: 0.0.0 +specifiers: + '@autorest/autorest': ~3.0.6118 + '@azure-tools/async-io': ~3.0.0 + '@azure-tools/autorest-extension-base': ~3.1.0 + '@azure-tools/codegen': ^2.5.276 + '@azure-tools/codegen-csharp': ~3.0.0 + '@azure-tools/codemodel': ~4.13.342 + '@azure-tools/codemodel-v3': ~3.1.0 + '@azure-tools/linq': ~3.1.0 + '@azure-tools/tasks': ~3.0.0 + '@microsoft.azure/autorest.testserver': ~2.9.3 + '@rush-temp/powershell': 'file:./projects/powershell.tgz' + '@types/js-yaml': 3.12.1 + '@types/mocha': 5.2.5 + '@types/node': 12.7.2 + '@types/xmlbuilder': 0.0.34 + '@typescript-eslint/eslint-plugin': ~2.0.0 + '@typescript-eslint/parser': ~2.0.0 + eslint: ~6.2.2 + js-yaml: 3.13.1 + mocha: 5.2.0 + mocha-typescript: 1.1.17 + source-map-support: 0.5.13 + typescript: ~3.7.0-beta + xmlbuilder: 10.1.1 diff --git a/common/scripts/install-run-rush.js b/common/scripts/install-run-rush.js index 7fc381d564..71ca9fe467 100644 --- a/common/scripts/install-run-rush.js +++ b/common/scripts/install-run-rush.js @@ -1,6 +1,25 @@ "use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // @@ -12,8 +31,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run-rush.js install // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const path = require("path"); -const fs = require("fs"); +const path = __importStar(require("path")); +const fs = __importStar(require("fs")); const install_run_1 = require("./install-run"); const PACKAGE_NAME = '@microsoft/rush'; const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; @@ -34,12 +53,12 @@ function _getRushVersion() { } catch (e) { throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + - 'The \'rushVersion\' field is either not assigned in rush.json or was specified ' + + "The 'rushVersion' field is either not assigned in rush.json or was specified " + 'using an unexpected syntax.'); } } function _run() { - const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ ...packageBinArgs /* [build, --to, myproject] */] = process.argv; + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv; // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the // appropriate binary inside the rush package to run const scriptName = path.basename(scriptPath); diff --git a/common/scripts/install-run.js b/common/scripts/install-run.js index 9c43223f7c..86912c7ccd 100644 --- a/common/scripts/install-run.js +++ b/common/scripts/install-run.js @@ -1,7 +1,27 @@ "use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See the @microsoft/rush package's LICENSE file for license information. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); +exports.runWithErrorAndStatusCode = exports.installAndRun = exports.findRushJsonFolder = exports.getNpmPath = exports.RUSH_JSON_FILENAME = void 0; // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // // This script is intended for usage in an automated build environment where a Node tool may not have @@ -12,10 +32,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const childProcess = require("child_process"); -const fs = require("fs"); -const os = require("os"); -const path = require("path"); +const childProcess = __importStar(require("child_process")); +const fs = __importStar(require("fs")); +const os = __importStar(require("os")); +const path = __importStar(require("path")); exports.RUSH_JSON_FILENAME = 'rush.json'; const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; const INSTALLED_FLAG_FILENAME = 'installed.flag'; @@ -46,6 +66,151 @@ function _parsePackageSpecifier(rawPackageSpecifier) { } return { name, version }; } +/** + * As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims + * unusable lines from the .npmrc file. + * + * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in + * the .npmrc file to provide different authentication tokens for different registry. + * However, if the environment variable is undefined, it expands to an empty string, which + * produces a valid-looking mapping with an invalid URL that causes an error. Instead, + * we'd prefer to skip that line and continue looking in other places such as the user's + * home directory. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities.copyAndTrimNpmrcFile() + */ +function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) { + console.log(`Copying ${sourceNpmrcPath} --> ${targetNpmrcPath}`); // Verbose + let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); + npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); + const resultLines = []; + // This finds environment variable tokens that look like "${VAR_NAME}" + const expansionRegExp = /\$\{([^\}]+)\}/g; + // Comment lines start with "#" or ";" + const commentRegExp = /^\s*[#;]/; + // Trim out lines that reference environment variables that aren't defined + for (const line of npmrcFileLines) { + let lineShouldBeTrimmed = false; + // Ignore comment lines + if (!commentRegExp.test(line)) { + const environmentVariables = line.match(expansionRegExp); + if (environmentVariables) { + for (const token of environmentVariables) { + // Remove the leading "${" and the trailing "}" from the token + const environmentVariableName = token.substring(2, token.length - 1); + // Is the environment variable defined? + if (!process.env[environmentVariableName]) { + // No, so trim this line + lineShouldBeTrimmed = true; + break; + } + } + } + } + if (lineShouldBeTrimmed) { + // Example output: + // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" + resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); + } + else { + resultLines.push(line); + } + } + fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); +} +/** + * syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file. + * If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder. + * + * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() + */ +function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish) { + const sourceNpmrcPath = path.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); + const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); + try { + if (fs.existsSync(sourceNpmrcPath)) { + _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath); + } + else if (fs.existsSync(targetNpmrcPath)) { + // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target + console.log(`Deleting ${targetNpmrcPath}`); // Verbose + fs.unlinkSync(targetNpmrcPath); + } + } + catch (e) { + throw new Error(`Error syncing .npmrc file: ${e}`); + } +} +let _npmPath = undefined; +/** + * Get the absolute path to the npm executable + */ +function getNpmPath() { + if (!_npmPath) { + try { + if (os.platform() === 'win32') { + // We're on Windows + const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); + const lines = whereOutput.split(os.EOL).filter((line) => !!line); + // take the last result, we are looking for a .cmd command + // see https://github.com/microsoft/rushstack/issues/759 + _npmPath = lines[lines.length - 1]; + } + else { + // We aren't on Windows - assume we're on *NIX or Darwin + _npmPath = childProcess.execSync('command -v npm', { stdio: [] }).toString(); + } + } + catch (e) { + throw new Error(`Unable to determine the path to the NPM tool: ${e}`); + } + _npmPath = _npmPath.trim(); + if (!fs.existsSync(_npmPath)) { + throw new Error('The NPM executable does not exist'); + } + } + return _npmPath; +} +exports.getNpmPath = getNpmPath; +function _ensureFolder(folderPath) { + if (!fs.existsSync(folderPath)) { + const parentDir = path.dirname(folderPath); + _ensureFolder(parentDir); + fs.mkdirSync(folderPath); + } +} +/** + * Create missing directories under the specified base directory, and return the resolved directory. + * + * Does not support "." or ".." path segments. + * Assumes the baseFolder exists. + */ +function _ensureAndJoinPath(baseFolder, ...pathSegments) { + let joinedPath = baseFolder; + try { + for (let pathSegment of pathSegments) { + pathSegment = pathSegment.replace(/[\\\/]/g, '+'); + joinedPath = path.join(joinedPath, pathSegment); + if (!fs.existsSync(joinedPath)) { + fs.mkdirSync(joinedPath); + } + } + } + catch (e) { + throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); + } + return joinedPath; +} +function _getRushTempFolder(rushCommonFolder) { + const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; + if (rushTempFolder !== undefined) { + _ensureFolder(rushTempFolder); + return rushTempFolder; + } + else { + return _ensureAndJoinPath(rushCommonFolder, 'temp'); + } +} /** * Resolve a package specifier to a static version */ @@ -95,37 +260,6 @@ function _resolvePackageVersion(rushCommonFolder, { name, version }) { } } } -let _npmPath = undefined; -/** - * Get the absolute path to the npm executable - */ -function getNpmPath() { - if (!_npmPath) { - try { - if (os.platform() === 'win32') { - // We're on Windows - const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); - const lines = whereOutput.split(os.EOL).filter((line) => !!line); - // take the last result, we are looking for a .cmd command - // see https://github.com/Microsoft/web-build-tools/issues/759 - _npmPath = lines[lines.length - 1]; - } - else { - // We aren't on Windows - assume we're on *NIX or Darwin - _npmPath = childProcess.execSync('which npm', { stdio: [] }).toString(); - } - } - catch (e) { - throw new Error(`Unable to determine the path to the NPM tool: ${e}`); - } - _npmPath = _npmPath.trim(); - if (!fs.existsSync(_npmPath)) { - throw new Error('The NPM executable does not exist'); - } - } - return _npmPath; -} -exports.getNpmPath = getNpmPath; let _rushJsonFolder; /** * Find the absolute path to the folder containing rush.json @@ -151,86 +285,6 @@ function findRushJsonFolder() { return _rushJsonFolder; } exports.findRushJsonFolder = findRushJsonFolder; -/** - * Create missing directories under the specified base directory, and return the resolved directory. - * - * Does not support "." or ".." path segments. - * Assumes the baseFolder exists. - */ -function _ensureAndJoinPath(baseFolder, ...pathSegments) { - let joinedPath = baseFolder; - try { - for (let pathSegment of pathSegments) { - pathSegment = pathSegment.replace(/[\\\/]/g, '+'); - joinedPath = path.join(joinedPath, pathSegment); - if (!fs.existsSync(joinedPath)) { - fs.mkdirSync(joinedPath); - } - } - } - catch (e) { - throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); - } - return joinedPath; -} -/** - * As a workaround, _syncNpmrc() copies the .npmrc file to the target folder, and also trims - * unusable lines from the .npmrc file. If the source .npmrc file not exist, then _syncNpmrc() - * will delete an .npmrc that is found in the target folder. - * - * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in - * the .npmrc file to provide different authentication tokens for different registry. - * However, if the environment variable is undefined, it expands to an empty string, which - * produces a valid-looking mapping with an invalid URL that causes an error. Instead, - * we'd prefer to skip that line and continue looking in other places such as the user's - * home directory. - * - * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() - */ -function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder) { - const sourceNpmrcPath = path.join(sourceNpmrcFolder, '.npmrc'); - const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); - try { - if (fs.existsSync(sourceNpmrcPath)) { - let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); - npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); - const resultLines = []; - // Trim out lines that reference environment variables that aren't defined - for (const line of npmrcFileLines) { - // This finds environment variable tokens that look like "${VAR_NAME}" - const regex = /\$\{([^\}]+)\}/g; - const environmentVariables = line.match(regex); - let lineShouldBeTrimmed = false; - if (environmentVariables) { - for (const token of environmentVariables) { - // Remove the leading "${" and the trailing "}" from the token - const environmentVariableName = token.substring(2, token.length - 1); - if (!process.env[environmentVariableName]) { - lineShouldBeTrimmed = true; - break; - } - } - } - if (lineShouldBeTrimmed) { - // Example output: - // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" - resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); - } - else { - resultLines.push(line); - } - } - fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); - } - else if (fs.existsSync(targetNpmrcPath)) { - // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target - fs.unlinkSync(targetNpmrcPath); - } - } - catch (e) { - throw new Error(`Error syncing .npmrc file: ${e}`); - } -} /** * Detects if the package in the specified directory is installed */ @@ -265,8 +319,8 @@ function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { } const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); if (fs.existsSync(nodeModulesFolder)) { - const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler', `install-run-${Date.now().toString()}`); - fs.renameSync(nodeModulesFolder, rushRecyclerFolder); + const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler'); + fs.renameSync(nodeModulesFolder, path.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`)); } } catch (e) { @@ -276,14 +330,14 @@ function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { function _createPackageJson(packageInstallFolder, name, version) { try { const packageJsonContents = { - 'name': 'ci-rush', - 'version': '0.0.0', - 'dependencies': { + name: 'ci-rush', + version: '0.0.0', + dependencies: { [name]: version }, - 'description': 'DON\'T WARN', - 'repository': 'DON\'T WARN', - 'license': 'MIT' + description: "DON'T WARN", + repository: "DON'T WARN", + license: 'MIT' }; const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME); fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); @@ -318,7 +372,7 @@ function _installPackage(packageInstallFolder, name, version) { */ function _getBinPath(packageInstallFolder, binName) { const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); - const resolvedBinName = (os.platform() === 'win32') ? `${binName}.cmd` : binName; + const resolvedBinName = os.platform() === 'win32' ? `${binName}.cmd` : binName; return path.resolve(binFolderPath, resolvedBinName); } /** @@ -333,23 +387,6 @@ function _writeFlagFile(packageInstallFolder) { throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`); } } -function _getRushTempFolder(rushCommonFolder) { - const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; - if (rushTempFolder !== undefined) { - _ensureFolder(rushTempFolder); - return rushTempFolder; - } - else { - return _ensureAndJoinPath(rushCommonFolder, 'temp'); - } -} -function _ensureFolder(folderPath) { - if (!fs.existsSync(folderPath)) { - const parentDir = path.dirname(folderPath); - _ensureFolder(parentDir); - fs.mkdirSync(folderPath); - } -} function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) { const rushJsonFolder = findRushJsonFolder(); const rushCommonFolder = path.join(rushJsonFolder, 'common'); @@ -368,12 +405,28 @@ function installAndRun(packageName, packageVersion, packageBinName, packageBinAr const statusMessageLine = new Array(statusMessage.length + 1).join('-'); console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL); const binPath = _getBinPath(packageInstallFolder, packageBinName); - const result = childProcess.spawnSync(binPath, packageBinArgs, { - stdio: 'inherit', - cwd: process.cwd(), - env: process.env - }); - return result.status; + const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + // Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to + // assign via the process.env proxy to ensure that we append to the right PATH key. + const originalEnvPath = process.env.PATH || ''; + let result; + try { + process.env.PATH = [binFolderPath, originalEnvPath].join(path.delimiter); + result = childProcess.spawnSync(binPath, packageBinArgs, { + stdio: 'inherit', + cwd: process.cwd(), + env: process.env + }); + } + finally { + process.env.PATH = originalEnvPath; + } + if (result.status !== null) { + return result.status; + } + else { + throw result.error || new Error('An unknown error occurred.'); + } } exports.installAndRun = installAndRun; function runWithErrorAndStatusCode(fn) { @@ -388,7 +441,7 @@ function runWithErrorAndStatusCode(fn) { } exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode; function _run() { - const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ rawPackageSpecifier, /* qrcode@^1.2.0 */ packageBinName, /* qrcode */ ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; + const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; if (!nodePath) { throw new Error('Unexpected exception: could not detect node path'); } diff --git a/powershell/main.ts b/powershell/main.ts index b8cfe84ed6..21590a6993 100644 --- a/powershell/main.ts +++ b/powershell/main.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { AutoRestExtension, } from '@azure-tools/autorest-extension-base'; -import { applyModifiers } from './plugins/modifiers'; -import { createCommands } from './plugins/create-commands'; -import { namer } from './plugins/ps-namer'; -import { powershell } from './plugins/powershell'; -import { addCompleter } from './plugins/add-azure-completers'; -import { csnamer } from './plugins/cs-namer'; -import { llcsharp } from './plugins/llcsharp'; +//import { applyModifiers } from './plugins/modifiers'; +//import { createCommands } from './plugins/create-commands'; +//import { namer } from './plugins/ps-namer'; +//import { powershell } from './plugins/powershell'; +//import { addCompleter } from './plugins/add-azure-completers'; +//import { csnamer } from './plugins/cs-namer'; +//import { llcsharp } from './plugins/llcsharp'; import { createInlinedPropertiesPlugin } from './plugins/plugin-create-inline-properties'; import { tweakModelPlugin } from './plugins/plugin-tweak-model'; import { tweakModelAzurePluginV2 } from './plugins/plugin-tweak-model-azure-v2'; @@ -27,13 +27,6 @@ require('source-map-support').install(); export async function main() { const pluginHost = new AutoRestExtension(); - pluginHost.Add('powershell', powershell); - pluginHost.Add('create-commands', createCommands); - pluginHost.Add('psnamer', namer); - pluginHost.Add('modifiers', applyModifiers); - pluginHost.Add('add-azure-completers', addCompleter); - pluginHost.Add('csnamer', csnamer); - pluginHost.Add('llcsharp', llcsharp); // Following are plugins moved from remodeler pluginHost.Add('tweakm4codemodel', tweakM4ModelPlugin); pluginHost.Add('tweakcodemodel-v2', tweakModelPlugin); diff --git a/powershell/plugins/add-azure-completers.ts b/powershell/plugins/add-azure-completers.ts deleted file mode 100644 index 3dd1a7f22c..0000000000 --- a/powershell/plugins/add-azure-completers.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, processCodeModel, ModelState } from '@azure-tools/codemodel-v3'; -import { values } from '@azure-tools/linq'; -import { Host } from '@azure-tools/autorest-extension-base'; - -type State = ModelState; - -const resourceGroupNames = new Set([ - 'resourcegroupname', - 'resourcegroup', -]); -const subscriptionIdNames = new Set([ - 'subscriptionid', -]); -const locationNames = new Set([ - 'location', -]); - -async function tweakModel(state: State): Promise { - const model = state.model; - for (const operation of values(model.commands.operations)) { - for (const parameter of values(operation.parameters)) { - const parameterName = parameter.details.csharp.name.toLowerCase(); - if (resourceGroupNames.has(parameterName)) { - parameter.details.csharp.completer = 'ResourceGroup'; - } - if (subscriptionIdNames.has(parameterName)) { - parameter.details.csharp.completer = 'SubscriptionId'; - } - if (locationNames.has(parameterName)) { - parameter.details.csharp.completer = 'Location'; - } - // 'Resource' - // 'ResourceId' - } - } - return model; -} - - -export async function addCompleter(service: Host) { - return processCodeModel(tweakModel, service, 'add-azure-completers'); -} diff --git a/powershell/plugins/create-commands.ts b/powershell/plugins/create-commands.ts deleted file mode 100644 index 1e9c2ee92e..0000000000 --- a/powershell/plugins/create-commands.ts +++ /dev/null @@ -1,454 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; -import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { Schema } from '../llcsharp/exports'; -import { Channel, Host } from '@azure-tools/autorest-extension-base'; -import { Lazy } from '@azure-tools/tasks'; -import { clone } from '@azure-tools/linq'; -import { verbs } from '../internal/verbs'; - -type State = ModelState; - - -// UNUSED: Moved to plugin-tweak-model.ts in remodeler -// For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. -export function titleToAzureServiceName(title: string): string { - const titleCamelCase = pascalCase(deconstruct(title)).trim(); - const serviceName = titleCamelCase - // Remove: !StartsWith(Management)AndContains(Management), Client, Azure, Microsoft, APIs, API, REST - .replace(/(?!^Management)(?=.*)Management|Client|Azure|Microsoft|APIs|API|REST/g, '') - // Remove: EndsWith(ServiceResourceProvider), EndsWith(ResourceProvider), EndsWith(DataPlane), EndsWith(Data) - .replace(/ServiceResourceProvider$|ResourceProvider$|DataPlane$|Data$/g, ''); - return serviceName || titleCamelCase; -} - - -const pluralizationService = new EnglishPluralizationService(); -pluralizationService.addWord('Database', 'Databases'); -pluralizationService.addWord('database', 'databases'); - - -interface CommandVariant { - alias: Array; - verb: string; - subject: string; - subjectPrefix: string; - variant: string; - action: string; -} - - -function fn(active: Array, remaining: Array, result: Array>): Array> { - if (length(active) || length(remaining)) { - if (length(remaining)) { - fn([...active, remaining[0]], remaining.slice(1), result); - fn(active, remaining.slice(1), result); - } else { - result.push(active); - } - } - return result; -} -function combinations(elements: Array) { - return fn([], elements, []); -} - -function splitOnPreposition(preposition: string, parts: Array) { - const i = parts.indexOf(preposition); - if (i > 0) { - return [ - parts.slice(0, i), - parts.slice(i + 1) - ]; - } - return undefined; -} - -function splitOnAnyPreposition(parts: Array) { - for (const p of ['with', 'at', 'by', 'for', 'in', 'of']) { - const result = splitOnPreposition(p, parts); - if (result && result[0].length > 0) { - // we found it, let's give it back. - return result; - } - } - return undefined; -} - - -export /* @internal */ class Inferrer { - commonParameters = new Array(); - verbMap!: { [operationIdMethod: string]: string }; - prefix!: string; - serviceName!: string; - subjectPrefix!: string; - isAzure!: boolean; - - constructor(private state: State) { - } - async init() { - this.commonParameters = await this.state.getValue('azure', false) ? [ - // 'resourceGroupName', - 'subscriptionId' - ] : []; - - this.verbMap = await this.state.getValue('verb-mapping') || {}; - this.isAzure = await this.state.getValue('azure', false); - this.prefix = await this.state.getValue('prefix'); - this.serviceName = titleToAzureServiceName(await this.state.getValue('service-name')); - this.state.setValue('service-name', this.serviceName); - - this.subjectPrefix = await this.state.getValue('subject-prefix'); - - this.state.setValue('isAzure', this.isAzure); - this.state.setValue('prefix', this.prefix); - - const model = this.state.model; - - this.state.message({ - Channel: Channel.Debug, Text: `[CMDLET-PREFIX] => '${model.details.default.prefix}'` - }); - - model.details.default.serviceName = this.serviceName; - this.state.message({ - Channel: Channel.Debug, Text: `[SERVICE-NAME] => '${model.details.default.serviceName}'` - }); - - model.details.default.subjectPrefix = this.subjectPrefix; - this.state.message({ - Channel: Channel.Debug, Text: `[SUBJECT-PREFIX] => '${model.details.default.subjectPrefix}'` - }); - - return this; - } - - async createCommands() { - const model = this.state.model; - this.state.model.commands = { - operations: new Dictionary(), - parameters: new Dictionary(), - }; - - this.state.message({ Channel: Channel.Debug, Text: 'detecting high level commands...' }); - - for (const operation of values(model.http.operations)) { - for (const variant of await this.inferCommandNames(operation, this.state)) { - // no common parameters (standard variations) - await this.addVariants(operation.parameters, operation, variant, '', this.state); - } - } - return model; - } - - inferCommand(operation: Array, group: string, suffix: Array = []): Array { - operation = operation.filter(each => each !== 'all'); - // no instant match - switch (length(operation)) { - case 0: - throw new Error('Missing operation id?'); - - case 1: - // simple operation, just an id with a single value - // OPERATION => OPERATION-GROUP - return [ - this.createCommandVariant(operation[0], deconstruct(group), suffix, this.state.model) - ]; - - case 2: - // should try to infer [SUBJECT] and [ACTION] from operation - if (verbs.has(operation[0])) { - // [ACTION][SUBJECT] - return [ - this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) - ]; - } - if (verbs.has(operation[1])) { - // [SUBJECT][ACTION] - return [ - this.createCommandVariant(operation[1], [...deconstruct(group), operation[0]], suffix, this.state.model) - ]; - - } - // can't tell which is the [ACTION] -- let's return it the way we used to, - // but now let's mention that we are doing that. - this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); - return [ - this.createCommandVariant(operation[0], [...deconstruct(group), operation[1]], suffix, this.state.model) - ]; - - } - // three or more words. - // first, see if it's an 'or' - const either = splitOnPreposition('or', operation); - if (either) { - // looks like we got two sets of operations from this. - return [ - ...this.inferCommand([...either[0], ...either[1].slice(1)], group, suffix), - ...this.inferCommand(either[1], group, suffix), - ]; - } - - // any other preposition? - const parts = splitOnAnyPreposition(operation); - if (parts) { - // so this is something like DoActionWithStyle - return [...this.inferCommand(parts[0], group, parts[1])]; - } - - // if not, then seek out a verb from there. - for (let i = 0; i < length(operation); i++) { - if (verbs.has(operation[i])) { - // if the action is first - if (i === 0) { - // everything else is the subject - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i + 1)] : operation.slice(i + 1), suffix, this.state.model)]; - } - if (i === length(operation) - 1) { - // if it's last, the subject would be the first thing - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(0, i)] : operation.slice(0, i), suffix, this.state.model)]; - } - - // otherwise - // things before are part of the subject - // things after the verb should be part of the suffix - return [this.createCommandVariant(operation[i], group ? [...deconstruct(group), ...operation.slice(i, i)] : operation.slice(i, i), [...suffix, ...operation.slice(i + 1)], this.state.model)]; - } - } - - // so couldn't tell what the action was. - // fallback to the original behavior with a warning. - this.state.warning(`Operation ${operation[0]}/${operation[1]} is inferred without finding action.`, [], {}); - return [this.createCommandVariant(operation[0], group ? [...deconstruct(group), ...operation.slice(1)] : operation.slice(1), [...suffix, ...operation.slice(1)], this.state.model)]; - } - - async inferCommandNames(op: http.HttpOperation, state: State): Promise> { - const operationId = op.operationId || ''; - - let [group, method] = operationId.split('_', 2); - if (!method) { - if (!group) { - // no operation id at all? - const path = op.path.replace(/{.*?}/g, '').replace(/\/+/g, '/').replace(/\/$/g, ''); - method = path.split('/').last; - } else { - // no group given, use string as method - method = group; - } - group = pascalCase(op.tags) || ''; - - } - - const groupWords = deconstruct(group); - groupWords[groupWords.length - 1] = pluralizationService.singularize(groupWords.last); - - group = pascalCase(groupWords); - const operation = deconstruct(method); - - // instant match - if (this.verbMap[method]) { - return [this.createCommandVariant(method, [group], [], state.model)]; - } - - // dig deeper. - return this.inferCommand(operation, group); - } - - async addVariant(vname: string, body: http.RequestBody | undefined, bodyParameterName: string, parameters: Array, operation: http.HttpOperation, variant: CommandVariant, state: State) { - const op = await this.addCommandOperation(vname, parameters, operation, variant, state); - - // if this has a body with it, let's add that parameter - if (body && body.schema) { - op.details.default.hasBody = true; - op.parameters.push(new components.IParameter(bodyParameterName, body.schema, { - details: { - default: { - description: body.schema.details.default.description, - name: pascalCase(bodyParameterName), - isBodyParameter: true, - } - } - })); - - // let's add a variant where it's expanded out. - // *IF* the body is an object - if (body.schema.type === JsonType.Object) { - const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state); - opExpanded.details.default.dropBodyParameter = true; - opExpanded.parameters.push(new components.IParameter(`${bodyParameterName}Body`, body.schema, { - details: { - default: { - description: body.schema.details.default.description, - name: pascalCase(`${bodyParameterName}Body`), - isBodyParameter: true, - } - } - })); - } - } - } - - - isNameConflict(model: codemodel.Model, variant: CommandVariant, vname: string) { - for (const each of values(model.commands.operations)) { - if (each.details.default.name === vname) { - return true; - } - } - return false; - } - - // for tracking unique operation identities - operationIdentities = new Set(); - - async addCommandOperation(vname: string, parameters: Array, operation: http.HttpOperation, variant: CommandVariant, state: State): Promise { - let apiversion = ''; - - for (const each of items(operation.responses)) { - for (const rsp of each.value) { - if (rsp.schema && rsp.schema.details && rsp.schema.details.default && rsp.schema.details.default.apiversion) { - apiversion = rsp.schema.details.default.apiversion; - break; - } - } - } - - // if vname is > 64 characters, let's trim it - // after trimming it, make sure there aren't any other operation with a name that's exactly the same - if (length(vname) > 64) { - const names = deconstruct(vname); - let newVName = ''; - for (let i = 0; i < length(names); i++) { - newVName = pascalCase(names.slice(0, i)); - if (length(newVName) > 60) { - break; - } - } - vname = newVName; - } - - // if we have an identical vname, let's add 'etc' - let fname = `${variant.verb}-${variant.subject}-${vname}`; - let n = 1; - while (this.operationIdentities.has(fname)) { - vname = `${vname.replace(/\d*$/g, '')}${n++}`; - fname = `${variant.verb}-${variant.subject}-${vname}`; - } - this.operationIdentities.add(fname); - - variant.variant = vname; - vname = pascalCase(vname); - const xmsMetadata = operation.pathExtensions ? operation.pathExtensions['x-ms-metadata'] ? clone(operation.pathExtensions['x-ms-metadata']) : {} : {}; - - return state.model.commands.operations[`${length(state.model.commands.operations)}`] = new command.CommandOperation(operation.operationId, { - asjob: operation.details.default.asjob ? true : false, - extensions: { - ...operation.pathExtensions, - 'x-ms-metadata': xmsMetadata - }, - ...variant, - details: { - ...operation.details, - default: { - ...operation.details.default, - subject: variant.subject, - subjectPrefix: variant.subjectPrefix, - verb: variant.verb, - name: vname, - alias: variant.alias - } - }, - operationId: operation.operationId, - parameters: parameters.map(httpParameter => { - // make it's own copy of the parameter since after this, - // the parameter can be altered for each operation individually. - const each = clone(httpParameter, false, undefined, undefined, ['schema', 'origin']); - each.details.default = { - ...each.details.default, - name: pascalCase(each.details.default.name), - httpParameter - }; - return each; - }), - callGraph: [operation], - }); - } - - async addVariants(parameters: Array, operation: http.HttpOperation, variant: CommandVariant, vname: string, state: State) { - // now synthesize parameter set variants multiplexed by the variants. - const [constants, requiredParameters] = values(parameters).bifurcate(parameter => parameter.details.default.constantValue || parameter.details.default.fromHost ? true : false); - const constantParameters = constants.map(each => `'${each.details.default.constantValue}'`); - - // the body parameter - const body = operation.requestBody; - const bodyParameterName = (operation.requestBody && operation.requestBody.extensions) ? operation.requestBody.extensions['x-ms-requestBody-name'] || 'bodyParameter' : ''; - - // all the properties in the body parameter - const bodyProperties = (body && body.schema) ? values(getAllProperties(body.schema)).where(property => !property.details.default.readOnly).toArray() : []; - - // smash body property names together - const bodyPropertyNames = bodyProperties.joinWith(each => each.details.default.name); - - // for each polymorphic body, we should do a separate variant that takes the polymorphic body type instead of the base type - const polymorphicBodies = (body && body.schema && body.schema.details.default.polymorphicChildren && length(body.schema.details.default.polymorphicChildren)) ? (>body.schema.details.default.polymorphicChildren).joinWith(child => child.details.default.name) : ''; - - // wait! "update" should be "set" if it's a POST - if (variant.verb === 'Update' && operation.method === http.HttpMethod.Put) { - variant.verb = 'Set'; - } - - // create variant - state.message({ Channel: Channel.Debug, Text: `${variant.verb}-${variant.subject} // ${operation.operationId} => ${JSON.stringify(variant)} taking ${requiredParameters.joinWith(each => each.name)}; ${constantParameters} ; ${bodyPropertyNames} ${polymorphicBodies ? `; Polymorphic bodies: ${polymorphicBodies} ` : ''}` }); - await this.addVariant(pascalCase([variant.action, vname]), body, bodyParameterName, [...constants, ...requiredParameters], operation, variant, state); - - const [pathParams, otherParams] = values(requiredParameters).bifurcate(each => each.in === ParameterLocation.Path); - const dvi = await state.getValue('disable-via-identity', false); - - if (!dvi && length(pathParams) > 0 && variant.action.toLowerCase() != 'list') { - // we have an operation that has path parameters, a good canididate for piping for identity. - await this.addVariant(pascalCase([variant.action, vname, 'via-identity']), body, bodyParameterName, [...constants, ...otherParams], operation, variant, state); - } - - } - - createCommandVariant(action: string, subject: Array, variant: Array, model: codemodel.Model): CommandVariant { - const verb = this.getPowerShellVerb(action); - if (verb === 'Invoke') { - // if the 'operation' name was "post" -- it's kindof redundant. - // so, only include the operation name in the group name if it's anything else - if (action.toLowerCase() !== 'post') { - subject = [action, ...subject]; - } - } - - return { - alias: [], - subject: pascalCase([...removeSequentialDuplicates(subject.map(each => pluralizationService.singularize(each)))]), - variant: pascalCase(variant), - verb, - subjectPrefix: model.details.default.subjectPrefix, - action - }; - } - - getPowerShellVerb(action: string): string { - const verb = this.verbMap[pascalCase(action)]; - if (verb) { - return verb; - } else { - return 'Invoke'; - } - } -} - - -export async function createCommands(service: Host) { - // return processCodeModel(commandCreator, service); - return processCodeModel(async (state) => { - return await (await new Inferrer(state).init()).createCommands(); - }, service, 'createCommands'); -} \ No newline at end of file diff --git a/powershell/plugins/cs-namer.ts b/powershell/plugins/cs-namer.ts deleted file mode 100644 index 4cf798a789..0000000000 --- a/powershell/plugins/cs-namer.ts +++ /dev/null @@ -1,245 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; - -import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { System } from '@azure-tools/codegen-csharp'; - -import { Host } from '@azure-tools/autorest-extension-base'; -import { Schema, SchemaDetails } from '../llcsharp/code-model'; -import { SchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; - -type State = ModelState; - - -function setPropertyNames(schema: Schema) { - // name each property in this schema - for (const propertySchema of values(schema.properties)) { - const propertyDetails = propertySchema.details.default; - - const className = schema.details.csharp.name; - - let pname = getPascalIdentifier(propertyDetails.name); - if (pname === className) { - pname = `${pname}Property`; - } - - if (pname === 'default') { - pname = '@default'; - } - - propertySchema.details.csharp = { - ...propertyDetails, - name: pname // and so are the propertyNmaes - }; - - if (propertyDetails.isNamedStream) { - propertySchema.details.csharp.namedStreamPropertyName = pascalCase(fixLeadingNumber([...deconstruct(propertyDetails.name), 'filename'])); - } - } - -} - - -function setSchemaNames(schemas: Dictionary, azure: boolean, serviceNamespace: string) { - const baseNamespace = new Set(); - const subNamespace = new Map>(); - // dolauli need to notice this -- schemas in the namespace of the lowest supported api version - // in Azure Mode, we want to always put schemas into the namespace of the lowest supported apiversion. - // otherwise, we just want to differientiate with a simple incremental numbering scheme. - - for (const schema of values(schemas)) { - let thisNamespace = baseNamespace; - let thisApiversion = ''; - - // create the namespace if required - if (azure) { - const metadata = schema.extensions && schema.extensions['x-ms-metadata']; - if (metadata) { - const apiVersions = | undefined>metadata.apiVersions; - if (apiVersions && length(apiVersions) > 0) { - thisApiversion = minimum(apiVersions); - thisNamespace = subNamespace.get(thisApiversion) || new Set(); - subNamespace.set(thisApiversion, thisNamespace); - } - } - } - - // for each schema, we're going to set the name - // to the suggested name, unless we have collisions - // at which point, we're going to add a number (for now?) - const details = schema.details.default; - let schemaName = getPascalIdentifier(details.name); - const apiName = (!thisApiversion) ? '' : getPascalIdentifier(`Api ${thisApiversion}`); - const ns = (!thisApiversion) ? [] : ['.', apiName]; - - - let n = 1; - while (thisNamespace.has(schemaName)) { - schemaName = getPascalIdentifier(`${details.name}_${n++}`); - } - thisNamespace.add(schemaName); - - // object types. - if (schema.type === JsonType.Object) { - schema.details.csharp = { - ...details, - apiversion: thisApiversion, - apiname: apiName, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), // objects have an interfaceName - internalInterfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal'])), // objects have an ineternal interfaceName for setting private members. - fullInternalInterfaceName: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName), 'Internal']))}`, - name: getPascalIdentifier(schemaName), - namespace: pascalCase([serviceNamespace, '.', 'Models', ...ns]), // objects have a namespace - fullname: `${pascalCase([serviceNamespace, '.', 'Models', ...ns])}.${getPascalIdentifier(schemaName)}`, - }; - } else if (schema.type === JsonType.String && schema.details.default.enum) { - // oh, it's an enum type - schema.details.csharp = { - ...details, - interfaceName: pascalCase(fixLeadingNumber(['I', ...deconstruct(schemaName)])), - name: getPascalIdentifier(schema.details.default.enum.name), - namespace: pascalCase([serviceNamespace, '.', 'Support']), - fullname: `${pascalCase([serviceNamespace, '.', 'Support'])}.${getPascalIdentifier(schema.details.default.enum.name)}`, - enum: { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name), - values: schema.details.default.enum.values.map(each => { - return { - ...each, - name: getPascalIdentifier(each.name), - description: each.description - }; - }) - } - }; - } else { - schema.details.csharp = { - ...details, - interfaceName: '', - internalInterfaceName: '', - name: schemaName, - namespace: '', - fullname: '' - }; - } - - // name each property in this schema - setPropertyNames(schema); - - // fix enum names - if (schema.details.default.enum) { - schema.details.csharp.enum = { - ...schema.details.default.enum, - name: getPascalIdentifier(schema.details.default.enum.name) - }; - - // and the value names themselves - for (const value of values(schema.details.csharp.enum.values)) { - value.name = getPascalIdentifier(value.name); - } - } - } - -} - -async function setOperationNames(state: State, resolver: SchemaDefinitionResolver) { - // keep a list of operation names that we've assigned. - const operationNames = new Set(); - - for (const operation of values(state.model.http.operations)) { - const details = operation.details.default; - - // come up with a name - const oName = getPascalIdentifier(details.name); - let i = 1; - let operationName = oName; - while (operationNames.has(operationName)) { - // if we have used that name, try again. - operationName = `${oName}${i++}`; - } - operationNames.add(operationName); - - operation.details.csharp = { - ...details, // inherit - name: operationName, - }; - - // parameters are camelCased. - for (const parameter of values(operation.parameters)) { - const parameterDetails = parameter.details.default; - - let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name))); - - if (propName === 'default') { - propName = '@default'; - } - - parameter.details.csharp = { - ...parameterDetails, - name: propName - }; - } - - for (const responses of values(operation.responses)) { - // per responseCode - for (const response of values(responses)) { - const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(response.schema, true, state.path('schemas', response.schema.details.default.name)) : undefined; - const headerTypeDefinition = response.headerSchema ? resolver.resolveTypeDeclaration(response.headerSchema, true, state.path('schemas', response.headerSchema.details.default.name)) : undefined; - let code = (System.Net.HttpStatusCode[response.responseCode] ? System.Net.HttpStatusCode[response.responseCode].value : response.responseCode).replace('global::System.Net.HttpStatusCode', ''); - let rawValue = code.replace(/\./, ''); - if (response.responseCode === 'default' || rawValue === 'default' || '') { - rawValue = 'any response code not handled elsewhere'; - code = 'default'; - } - response.details.csharp = { - ...response.details.default, - responseType: responseTypeDefinition ? responseTypeDefinition.declaration : '', - headerType: headerTypeDefinition ? headerTypeDefinition.declaration : '', - name: (length(responses) <= 1) ? - camelCase(fixLeadingNumber(deconstruct(`on ${code}`))) : // the common type (or the only one.) - camelCase(fixLeadingNumber(deconstruct(`on ${code} ${response.mimeTypes[0]}`))), - description: (length(responses) <= 1) ? - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}).` : - `a delegate that is called when the remote service returns ${response.responseCode} (${rawValue}) with a Content-Type matching ${response.mimeTypes.join(',')}.` - - }; - } - } - } -} - -async function nameStuffRight(state: State): Promise { - const resolver = new SchemaDefinitionResolver(); - const model = state.model; - - // set the namespace for the service - const serviceNamespace = await state.getValue('namespace', 'Sample.API'); - const azure = await state.getValue('azure', false) || await state.getValue('azure-arm', false); - const clientName = getPascalIdentifier(model.details.default.name); - - // dolauli see model.details.csharp for c# related staff - // set c# client details (name) - model.details.csharp = { - ...model.details.default, // copy everything by default - name: clientName, - namespace: serviceNamespace, - fullname: `${serviceNamespace}.${clientName}` - }; - - setSchemaNames(>model.schemas, azure, serviceNamespace); - await setOperationNames(state, resolver); - - return model; -} - - -export async function csnamer(service: Host) { - // dolauli add names for http operations and schemas - return processCodeModel(nameStuffRight, service, 'csnamer'); -} - diff --git a/powershell/plugins/llcsharp.ts b/powershell/plugins/llcsharp.ts deleted file mode 100644 index b4735cdffb..0000000000 --- a/powershell/plugins/llcsharp.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { Host } from '@azure-tools/autorest-extension-base'; -import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; -import { join } from 'path'; -import { Model } from '../llcsharp/code-model'; -import { State } from '../llcsharp/generator'; -import { Project } from '../llcsharp/project'; -import { Dictionary } from '@azure-tools/linq'; - -const resources = `${__dirname}/../../resources`; - -export async function llcsharp(service: Host) { - try { - const project = await new Project(service).init(); - - await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); - - // recursive copy resources - await copyResources(join(resources, 'runtime', 'csharp', 'client'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - await copyResources(join(resources, 'runtime', 'csharp', 'pipeline'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - // Note: - // we are using the Carbon.Json library, but we don't *really* want to expose that as public members where we don't have to - // and I don't want to make code changes in the source repository, so I can keep merging from upstream as simple as possible. - // so, we're converting as much as possible to internal, and exposing only what must be exposed to make the code compile. - - await copyResources(join(resources, 'runtime', 'csharp', 'json'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), { - ...project.overrides, - 'public': 'internal', - 'internal (.*) class JsonNumber': 'public $1 class JsonNumber', - 'internal (.*) class JsonObject': 'public $1 class JsonObject', - 'internal (.*) class JsonNode': 'public $1 class JsonNode', - 'internal (.*) class JsonString': 'public $1 class JsonString', - 'internal (.*) class XNodeArray': 'public $1 class XNodeArray', - 'internal (.*) class JsonArray': 'public $1 class JsonArray', - 'internal(.*) class JsonTokenizer': 'public$1 class JsonTokenizer', - 'internal(.*) class JsonParser': 'public$1 class JsonParser', - 'internal(.*) class TokenReader': 'public$1 class TokenReader', - 'internal(.*) class SourceReader': 'public$1 class SourceReader', - 'internal(.*) class (.*)Converter': 'public$1 class $2Converter', - 'internal(.*) interface IJsonSerializable': 'public$1 interface IJsonSerializable', - 'internal override string ToString': 'public override string ToString', - 'internal void Add\\(': 'public void Add(', - 'internal bool ContainsKey\\(': 'public bool ContainsKey(', - 'internal bool Remove\\(': 'public bool Remove(', - 'internal bool TryGetValue\\(': 'public bool TryGetValue(', - 'internal (.*) JsonNode this\\[': 'public $1 JsonNode this[', - - 'internal ICollection Values': 'public ICollection Values', - 'internal ICollection Keys': 'public ICollection Keys', - 'internal bool IsReadOnly': 'public bool IsReadOnly', - 'internal (.*) int Count': 'public $1 int Count', - 'internal bool Contains\\(': 'public bool Contains(', - 'internal(.*) bool Equals': 'public$1 bool Equals', - 'internal (.*) int GetHashCode': 'public $1 int GetHashCode', - 'internal void Dispose': 'public void Dispose', - 'internal (.*) operator': 'public $1 operator', - 'internal object FromJson\\(': 'public object FromJson(', - 'internal JsonNode ToJson\\(': 'public JsonNode ToJson(', - - }); - - if (project.xmlSerialization) { - await copyResources(join(resources, 'runtime', 'csharp', 'xml'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - } - - if (project.azure) { - await copyResources(join(resources, 'runtime', 'csharp.azure'), async (fname, content) => service.WriteFile(join(project.runtimefolder, fname), content, undefined, 'source-file-csharp'), project.overrides); - } - - } catch (E) { - console.error(`${__filename} - ${E.stack}/${E.message}`); - throw E; - } -} diff --git a/powershell/plugins/modifiers.ts b/powershell/plugins/modifiers.ts deleted file mode 100644 index e6928d1e7f..0000000000 --- a/powershell/plugins/modifiers.ts +++ /dev/null @@ -1,701 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, ModelState, command } from '@azure-tools/codemodel-v3'; -import { Host, Channel } from '@azure-tools/autorest-extension-base'; -import { pascalCase } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; - -type State = ModelState; - -let directives: Array = []; - -interface WhereCommandDirective { - select?: string; - where: { - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - }; - set?: { - 'alias': Array | string; - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - 'parameter-description'?: string; - 'completer'?: { - name: string; - description: string; - script: string; - }; - 'default'?: { - name: string; - description: string; - script: string; - }; - }; - 'clear-alias': boolean; - hide?: boolean; -} -interface RemoveCommandDirective { - select?: string; - where: { - 'subject'?: string; - 'subject-prefix'?: string; - 'verb'?: string; - 'variant'?: string; - 'parameter-name'?: string; - }; - remove: boolean; -} - - -function hasSpecialChars(str: string): boolean { - return !/^[a-zA-Z0-9]+$/.test(str); -} - - -function getFilterError(whereObject: any, prohibitedFilters: Array, selectionType: string): string { - let error = ''; - for (const each of values(prohibitedFilters)) { - if (whereObject[each] !== undefined) { - error += `Can't filter by ${each} when selecting command. `; - } - } - - return error; -} - -function getSetError(setObject: any, prohibitedSetters: Array, selectionType: string): string { - let error = ''; - for (const each of values(prohibitedSetters)) { - if (setObject[each] !== undefined) { - error += `Can't set ${each} when a ${selectionType} is selected. `; - } - } - - return error; -} - - -function isWhereCommandDirective(it: any): it is WhereCommandDirective { - const directive = it; - const select = directive.select; - const where = directive.where; - const set = directive.set; - if (directive.remove === undefined && where && (where.verb || where.variant || where['parameter-name'] || where.subject || where['subject-prefix'] || directive.hide || select === 'command' || select === 'parameter' || directive['clear-alias'])) { - const prohibitedFilters = ['model-name', 'property-name', 'enum-name', 'enum-value-name']; - let error = getFilterError(where, prohibitedFilters, 'command'); - - if (set !== undefined) { - const prohibitedSetters = ['property-name', 'property-description', ' model-name', 'enum-name', 'enum-value-name']; - error += getSetError(set, prohibitedSetters, 'command'); - } - - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); - } - - return true; - } - - return false; -} - -function isRemoveCommandDirective(it: any): it is RemoveCommandDirective { - const directive = it; - const where = directive.where; - const remove = directive.remove; - if (where && remove && (where.subject || where.verb || where.variant || where['subject-prefix'] || where['parameter-name'] || directive.select === 'command') && directive.select !== 'parameter') { - return true; - } - - return false; -} - - -interface WhereModelDirective { - select?: string; - where: { - 'model-name'?: string; - 'model-fullname'?: string; - 'model-namespace'?: string; - 'property-name'?: string; - }; - set: { - 'suppress-format'?: boolean; - 'format-table'?: { - 'properties'?: Array; - 'exclude-properties'?: Array; - 'labels'?: { [name: string]: string }; - 'width'?: { [name: string]: number }; - }; - 'model-name'?: string; - 'property-name'?: string; - 'property-description'?: string; - }; -} - -function isWhereModelDirective(it: any): it is WhereModelDirective { - const directive = it; - const where = directive.where; - const set = directive.set; - - - if (where && set && (where['model-name'] || where['model-fullname'] || where['model-namespace'] || where['property-name'] || directive.select === 'model')) { - const prohibitedFilters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; - let error = getFilterError(where, prohibitedFilters, 'enum'); - const prohibitedSetters = ['enum-name', 'enum-value-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; - error += getSetError(set, prohibitedSetters, 'enum'); - const modelSelectNameConflict = []; - let modelSelectNameType = ''; - if (where['model-name']) { - modelSelectNameType = 'model-name'; - if (where['model-fullname']) { - modelSelectNameConflict.push('model-fullname'); - } - - if (where['model-namespace']) { - modelSelectNameConflict.push('model-namespace'); - } - } else if (where['model-fullname']) { - modelSelectNameType = 'model-fullname'; - if (where['model-name']) { - modelSelectNameConflict.push('model-name'); - } - - if (where['model-namespace']) { - modelSelectNameConflict.push('model-namespace'); - } - } else if (where['model-namespace']) { - modelSelectNameType = 'model-namespace'; - if (where['model-fullname']) { - modelSelectNameConflict.push('model-fullname'); - } - - if (where['model-name']) { - modelSelectNameConflict.push('model-name'); - } - } - - if (length(modelSelectNameConflict) > 0) { - error += `Can't select ${modelSelectNameType} and ${modelSelectNameConflict} at the same time`; - } - - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}.Reason: ${error}.`); - } - - return true; - - } - return false; -} - -interface WhereEnumDirective { - select?: string; - where: { - 'enum-name'?: string; - 'enum-value-name'?: string; - }; - set: { - 'enum-name'?: string; - 'enum-value-name'?: string; - }; -} - -function isWhereEnumDirective(it: any): it is WhereEnumDirective { - const directive = it; - const where = directive.where; - const set = directive.set; - if (where && set && (where['enum-name'] || where['enum-value-name'] || directive.select === 'enum')) { - const prohibitedFilters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name']; - let error = getFilterError(where, prohibitedFilters, 'enum'); - const prohibitedSetters = ['model-name', 'property-name', 'subject', 'subject-prefix', 'verb', 'variant', 'parameter-name', 'parameter-description', 'completer', 'default']; - error += getSetError(set, prohibitedSetters, 'enum'); - if (error) { - throw Error(`Incorrect Directive: ${JSON.stringify(it, null, 2)}. Reason: ${error}.`); - } - - return true; - } - return false; -} - -async function tweakModel(state: State): Promise { - - // only look at directives without the `transform` node. - // dolauli for directives with transform are implemented in autorest core - for (const directive of directives.filter(each => !each.transform)) { - const getPatternToMatch = (selector: string | undefined): RegExp | undefined => { - return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined; - }; - - if (isWhereCommandDirective(directive)) { - const selectType = directive.select; - const clearAlias = directive['clear-alias']; - const subjectRegex = getPatternToMatch(directive.where['subject']); - const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); - const verbRegex = getPatternToMatch(directive.where.verb); - const variantRegex = getPatternToMatch(directive.where.variant); - const parameterRegex = getPatternToMatch(directive.where['parameter-name']); - - const alias = - (directive.set !== undefined) ? - (directive.set.alias !== undefined) ? - !Array.isArray(directive.set.alias) ? - [directive.set.alias] - : directive.set.alias - : undefined - : undefined; - const subjectReplacer = (directive.set !== undefined) ? directive.set['subject'] : undefined; - const subjectPrefixReplacer = (directive.set !== undefined) ? directive.set['subject-prefix'] : undefined; - const verbReplacer = (directive.set !== undefined) ? directive.set.verb : undefined; - const variantReplacer = (directive.set !== undefined) ? directive.set.variant : undefined; - const parameterReplacer = (directive.set !== undefined) ? directive.set['parameter-name'] : undefined; - const paramDescriptionReplacer = (directive.set !== undefined) ? directive.set['parameter-description'] : undefined; - const paramCompleterReplacer = (directive.set !== undefined) ? directive.set['completer'] : undefined; - const paramDefaultReplacer = (directive.set !== undefined) ? directive.set['default'] : undefined; - - // select all operations - let operations: Array = values(state.model.commands.operations).toArray(); - if (subjectRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.subject}`.match(subjectRegex)) - .toArray(); - } - - if (subjectPrefixRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.subjectPrefix}`.match(subjectPrefixRegex)) - .toArray(); - } - - if (verbRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.verb}`.match(verbRegex)) - .toArray(); - } - - if (variantRegex) { - operations = values(operations) - .where(operation => - !!`${operation.details.csharp.name}`.match(variantRegex)) - .toArray(); - } - - if (parameterRegex && selectType === 'command') { - operations = values(operations) - .where(operation => values(allVirtualParameters(operation.details.csharp.virtualParameters)) - .any(parameter => !!`${parameter.name}`.match(parameterRegex))) - .toArray(); - } - - if (parameterRegex && (selectType === undefined || selectType === 'parameter')) { - const parameters = values(operations) - .selectMany(operation => allVirtualParameters(operation.details.csharp.virtualParameters)) - .where(parameter => !!`${parameter.name}`.match(parameterRegex)) - .toArray(); - for (const p of values(parameters)) { - const parameter = p; - const prevName = parameter.name; - parameter.name = parameterReplacer ? parameterRegex ? parameter.name.replace(parameterRegex, parameterReplacer) : parameterReplacer : parameter.name; - parameter.description = paramDescriptionReplacer ? paramDescriptionReplacer : parameter.description; - parameter.completerInfo = paramCompleterReplacer ? paramCompleterReplacer : parameter.completerInfo; - parameter.defaultInfo = paramDefaultReplacer ? paramDefaultReplacer : parameter.defaultInfo; - - if (clearAlias) { - parameter.alias = []; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from parameter ${parameter.name}.` - }); - } - - if (alias) { - const parsedAlias = new Array(); - for (const each of values(alias)) { - parsedAlias.push(hasSpecialChars(each) ? prevName.replace(parameterRegex, each) : each); - } - - parameter.alias = [...new Set(values(parameter.alias, parsedAlias).toArray())]; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to parameter ${parameter.name}.` - }); - } - - if (parameterReplacer) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed parameter-name from ${prevName} to ${parameter.name}.` - }); - } - - if (paramDescriptionReplacer) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Set parameter-description from parameter ${parameter.name}.` - }); - } - } - - } else if (operations) { - for (const operation of values(operations)) { - const getCmdletName = (verb: string, subjectPrefix: string, subject: string, variantName: string): string => { - return `${verb}-${subjectPrefix}${subject}${variantName ? `_${variantName}` : ''}`; - }; - - const prevSubject = operation.details.csharp.subject; - const prevSubjectPrefix = operation.details.csharp.subjectPrefix; - const prevVerb = operation.details.csharp.verb; - const prevVariantName = operation.details.csharp.name; - const oldCommandName = getCmdletName(prevVerb, prevSubjectPrefix, prevSubject, prevVariantName); - - // set values - operation.details.csharp.subject = subjectReplacer ? subjectRegex ? prevSubject.replace(subjectRegex, subjectReplacer) : subjectReplacer : prevSubject; - operation.details.csharp.subjectPrefix = subjectPrefixReplacer !== undefined ? subjectPrefixRegex ? prevSubjectPrefix.replace(subjectPrefixRegex, subjectPrefixReplacer) : subjectPrefixReplacer : prevSubjectPrefix; - operation.details.csharp.verb = verbReplacer ? verbRegex ? prevVerb.replace(verbRegex, verbReplacer) : verbReplacer : prevVerb; - operation.details.csharp.name = variantReplacer ? variantRegex ? prevVariantName.replace(variantRegex, variantReplacer) : variantReplacer : prevVariantName; - operation.details.csharp.hidden = (directive.hide !== undefined) ? !!directive.hide : operation.details.csharp.hidden; - - const newSubject = operation.details.csharp.subject; - const newSubjectPrefix = operation.details.csharp.subjectPrefix; - const newVerb = operation.details.csharp.verb; - const newVariantName = operation.details.csharp.name; - const newCommandName = getCmdletName(newVerb, newSubjectPrefix, newSubject, newVariantName); - - // just the subject prefix can be an empty string - if (subjectPrefixReplacer !== undefined || subjectReplacer || verbReplacer || variantReplacer) { - const modificationMessage = `[DIRECTIVE] Changed command from ${oldCommandName} to ${newCommandName}. `; - state.message({ - Channel: Channel.Debug, Text: modificationMessage - }); - } - - if (clearAlias) { - operation.details.csharp.alias = []; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Cleared aliases from command ${newCommandName}.` - }); - } - - if (alias) { - const getParsedAlias = (rawAlias: string) => { - return rawAlias.replace('${verb}', operation.details.csharp.verb) - .replace('${subject-prefix}', operation.details.csharp.subjectPrefix) - .replace('${subject}', operation.details.csharp.subject) - .replace('${variant}', operation.details.csharp.name); - }; - - const parsedAlias = new Array(); - for (const each of values(alias)) { - parsedAlias.push(getParsedAlias(each)); - } - - operation.details.csharp.alias = [...new Set(values(operation.details.csharp.alias, parsedAlias).toArray())]; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Added alias ${parsedAlias} to command ${newCommandName}.` - }); - } - } - } - - continue; - } - - if (isWhereModelDirective(directive)) { - const selectType = directive.select; - const modelNameRegex = getPatternToMatch(directive.where['model-name']); - const modelFullNameRegex = getPatternToMatch(directive.where['model-fullname']); - const modelNamespaceRegex = getPatternToMatch(directive.where['model-namespace']); - const propertyNameRegex = getPatternToMatch(directive.where['property-name']); - - const modelNameReplacer = directive.set['model-name']; - const propertyNameReplacer = directive.set['property-name']; - const propertyDescriptionReplacer = directive.set['property-description']; - const formatTable = directive.set['format-table']; - const suppressFormat = directive.set['suppress-format']; - - // select all models - let models = values(state.model.schemas).toArray(); - if (modelNameRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.name}`.match(modelNameRegex)) - .toArray(); - } - - if (modelFullNameRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.fullname}`.match(modelFullNameRegex)) - .toArray(); - } - - if (modelNamespaceRegex) { - models = values(models) - .where(model => - !!`${model.details.csharp.namespace}`.match(modelNamespaceRegex)) - .toArray(); - } - - if (propertyNameRegex && selectType === 'model') { - models = values(models) - .where(model => values(allVirtualProperties(model.details.csharp.virtualProperties)) - .any(property => !!`${property.name}`.match(propertyNameRegex))) - .toArray(); - } - - if (propertyNameRegex && (selectType === undefined || selectType === 'property')) { - const properties = values(models) - .selectMany(model => allVirtualProperties(model.details.csharp.virtualProperties)) - .where(property => !!`${property.name}`.match(propertyNameRegex)) - .toArray(); - for (const property of values(properties)) { - const prevName = property.name; - property.name = propertyNameReplacer ? propertyNameRegex ? property.name.replace(propertyNameRegex, propertyNameReplacer) : propertyNameReplacer : property.name; - property.description = propertyDescriptionReplacer ? propertyDescriptionReplacer : property.description; - - if (!property.name) { - state.message({ Channel: Channel.Error, Text: `Directive '${directive.where['model-name'] || directive.where['model-fullname']}/${directive.where['property-name']}' attempted to change '${prevName}' to '' ` }); - } - if (propertyNameRegex) { - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed property-name from ${prevName} to ${property.name}.` - }); - } - } - - } else if (models) { - for (const model of values(models)) { - - if (suppressFormat) { - model.details.csharp.suppressFormat = true; - } - - if (formatTable !== undefined && !suppressFormat) { - const properties = allVirtualProperties(model.details.csharp.virtualProperties); - const propertiesToExclude = formatTable['exclude-properties']; - const propertiesToInclude = formatTable.properties; - const labels = formatTable.labels; - const widths = formatTable.width; - if (labels) { - const parsedLabels = new Dictionary(); - for (const label of items(labels)) { - parsedLabels[label.key.toLowerCase()] = label.value; - } - - for (const property of values(properties)) { - if (Object.keys(parsedLabels).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.label = parsedLabels[property.name.toLowerCase()]; - } - } - } - - if (widths) { - const parsedWidths = new Dictionary(); - for (const w of items(widths)) { - parsedWidths[w.key.toLowerCase()] = w.value; - } - - for (const property of values(properties)) { - if (Object.keys(parsedWidths).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.width = parsedWidths[property.name.toLowerCase()]; - } - } - } - - if (propertiesToInclude) { - const indexes = new Dictionary(); - for (const item of items(propertiesToInclude)) { - indexes[item.value.toLowerCase()] = item.key; - } - - for (const property of values(properties)) { - if (propertiesToInclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { - if (property.format === undefined) { - property.format = {}; - } - - property.format.index = indexes[property.name.toLowerCase()]; - } else { - property.format = { suppressFormat: true }; - } - } - } - - if (propertiesToExclude) { - for (const property of values(properties)) { - if (propertiesToExclude.map(x => x.toLowerCase()).includes(property.name.toLowerCase())) { - property.format = { suppressFormat: true }; - } - } - } - } - - const prevName = model.details.csharp.name; - model.details.csharp.name = modelNameReplacer ? modelNameRegex ? model.details.csharp.name.replace(modelNameRegex, modelNameReplacer) : modelNameReplacer : model.details.csharp.name; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed model-name from ${prevName} to ${model.details.csharp.name}.` - }); - } - } - - continue; - } - - if (isWhereEnumDirective(directive)) { - const enumNameRegex = getPatternToMatch(directive.where['enum-name']); - const enumValueNameRegex = getPatternToMatch(directive.where['enum-value-name']); - - const enumNameReplacer = directive.set['enum-name']; - const enumValueNameReplacer = directive.set['enum-value-name']; - - let enums = values(state.model.schemas) - .where(each => each.details.csharp.enum !== undefined) - .toArray(); - - if (enumNameRegex) { - enums = values(enums) - .where(each => !!`${each.details.csharp.name}`.match(enumNameRegex)) - .toArray(); - } - - if (enumValueNameRegex) { - const enumsValues = values(enums) - .selectMany(each => each.details.csharp.enum ? each.details.csharp.enum.values : []) - .where(each => !!`${each.name}`.match(enumValueNameRegex)) - .toArray(); - for (const enumValue of values(enumsValues)) { - const prevName = enumValue.name; - enumValue.name = enumValueNameReplacer ? enumNameRegex ? enumValue.name.replace(enumValueNameRegex, enumValueNameReplacer) : enumValueNameReplacer : prevName; - if (enumValueNameRegex) { - const enumNames = values(enums) - .select(each => each.details.csharp.name) - .toArray(); - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-value-name from ${prevName} to ${enumValue.name}. Enum: ${JSON.stringify(enumNames, null, 2)}` - }); - } - } - } else { - for (const each of values(enums)) { - const prevName = each.details.csharp.name; - each.details.csharp.name = enumNameReplacer ? enumNameRegex ? each.details.csharp.name.replace(enumNameRegex, enumNameReplacer) : enumNameReplacer : prevName; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Changed enum-name from ${prevName} to ${each.details.csharp.name}.` - }); - } - } - - continue; - } - - - if (isRemoveCommandDirective(directive)) { - const selectType = directive.select; - const subjectRegex = getPatternToMatch(directive.where.subject); - const subjectPrefixRegex = getPatternToMatch(directive.where['subject-prefix']); - const verbRegex = getPatternToMatch(directive.where.verb); - const variantRegex = getPatternToMatch(directive.where.variant); - const parameterRegex = getPatternToMatch(directive.where['parameter-name']); - - if (subjectRegex || subjectPrefixRegex || verbRegex || variantRegex || (parameterRegex && selectType === 'command')) { - // select all operations first then reduce by finding the intersection with selectors - let operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .select(operation => operation.key) - .toArray()); - - if (subjectRegex) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.subject}`.match(subjectRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (subjectPrefixRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.subjectPrefix}`.match(subjectPrefixRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (verbRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.verb}`.match(verbRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (variantRegex && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => !!`${operation.value.details.csharp.name}`.match(variantRegex) && operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - if (parameterRegex && selectType === 'command' && operationsToRemoveKeys.size > 0) { - operationsToRemoveKeys = new Set(items(state.model.commands.operations) - .where(operation => values(allVirtualParameters(operation.value.details.csharp.virtualParameters)) - .any(parameter => !!`${parameter.name}`.match(parameterRegex))) - .where(operation => operationsToRemoveKeys.has(operation.key)) - .select(operation => operation.key) - .toArray()); - } - - for (const key of values(operationsToRemoveKeys)) { - const operationInfo = state.model.commands.operations[key].details.csharp; - state.message({ - Channel: Channel.Debug, Text: `[DIRECTIVE] Removed command ${operationInfo.verb}-${operationInfo.subjectPrefix}${operationInfo.subject}${operationInfo.name ? `_${operationInfo.name}` : ''}` - }); - - delete state.model.commands.operations[key]; - } - } - - continue; - } - } - - const operationIdentities = new Set(); - for (const operation of values(state.model.commands.operations)) { - const details = operation.details.csharp; - - let fname = `${details.verb} -${details.subject} -${details.name} `; - let n = 1; - - while (operationIdentities.has(fname)) { - details.name = pascalCase(`${details.name.replace(/\d*$/g, '')} ${n++}`); - fname = pascalCase(`${details.verb} -${details.subject} -${details.name}`); - } - operationIdentities.add(fname); - } - - return state.model; -} - -export async function applyModifiers(service: Host) { - // dolauli implement directives - const allDirectives = await service.GetValue('directive'); - directives = values(allDirectives) - // .select(directive => directive) - .where(directive => isWhereCommandDirective(directive) || isWhereModelDirective(directive) || isWhereEnumDirective(directive) || isRemoveCommandDirective(directive)) - .toArray(); - - return processCodeModel(tweakModel, service, 'modifiers'); -} diff --git a/powershell/plugins/plugin-tweak-model-azure.ts b/powershell/plugins/plugin-tweak-model-azure.ts deleted file mode 100644 index 4fb91a2f8e..0000000000 --- a/powershell/plugins/plugin-tweak-model-azure.ts +++ /dev/null @@ -1,175 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - -import { codemodel, JsonType, processCodeModel, ModelState, getAllProperties, HttpMethod, schema } from '@azure-tools/codemodel-v3'; -import { keys, length, values } from '@azure-tools/linq'; - -import { Channel, Host } from '@azure-tools/autorest-extension-base'; -type State = ModelState; - -const xmsPageable = 'x-ms-pageable'; - -async function tweakModel(state: State): Promise { - const model = state.model; - - // service.Message({ Channel: Channel.Debug, Text: "THIS IS THE AZURE TWEAKER" }); - - // TODO: - // look at models, and extract out any case that has an IRESOURCE, IPROXYRESOURCE, etc. - // and use the common versions of those models. - - // Is the result marked x-ms-pagable? - // identify the next link (null means just get the results as an array) - // if nextLinkName is null, then it won't actually page, but we'd like to unroll the contents anyway. - for (const operation of values(model.http.operations)) { - if (operation.extensions && operation.extensions[xmsPageable]) { - // it's marked pagable. - operation.details.default.pageable = { - responseType: 'pageable', - nextLinkName: operation.extensions[xmsPageable].nextLinkName || undefined, - itemName: operation.extensions[xmsPageable].itemName || 'value', - operationName: operation.extensions[xmsPageable].operationName || `${operation.operationId}Next`, - }; - continue; - } - - // let's just check to see if it looks like it's supposed to be a collection - for (const responses of values(operation.responses)) { - for (const response of values(responses)) { - // does the response have a schema? - if (response.schema) { - const schema = response.schema; - - // is this just an array response? - if (schema.type === JsonType.Array) { - operation.details.default.pageable = { - responseType: 'array', - }; - continue; - } - - // if it returns an object, let's see what's inside... - if (schema.type === JsonType.Object) { - - // does it have a single member that is an array (ie, value : [...]) - if (length(schema.properties) === 1 && length(schema.allOf) === 0) { - const propertyName = keys(schema.properties).first(); - if (propertyName) { - const property = schema.properties[propertyName]; - if (property.schema.type === JsonType.Array) { - // nested array! - operation.details.default.pageable = { - responseType: 'nested-array', - itemName: propertyName, - }; - } - continue; - } - } - - // does it kinda look like a x-ms-pagable (value/nextlink?) - if (length(schema.properties) === 2 && length(schema.allOf) === 0) { - if (schema.properties.nextLink) { - const propertyName = keys(schema.properties).where(each => each !== 'nextLink').first(); - if (propertyName) { - const property = schema.properties[propertyName]; - if (property.schema.type === JsonType.Array) { - // nested array! - operation.details.default.pageable = { - responseType: 'nested-array', - itemName: propertyName, - nextLinkName: 'nextLink' - }; - } - continue; - } - } - - } - - } - } - - } - } - } - - // make sure that all operations with lro have an options block. - for (const operation of values(model.http.operations)) { - if (operation.extensions && operation.extensions['x-ms-long-running-operation']) { - operation.details.default.asjob = true; - - operation.details.default.lro = operation.extensions['x-ms-long-running-operation-options'] || { - 'final-state-via': 'default' - }; - - // LRO 201 and 202 responses are handled internally, so remove any 201/202 responses in the operation - delete operation.responses['201']; - delete operation.responses['202']; - } - } - - // Api Version parameter handling for Azure. - // if there is only a single api-version for the operation, let's just make it a constant - // otherwise, we need to make it selectable, but default to the 'latest' version there is. - for (const operation of values(model.http.operations)) { - const apiVersions = operation.pathExtensions && operation.pathExtensions['x-ms-metadata'] ? operation.pathExtensions['x-ms-metadata'].apiVersions : undefined; - for (const parameter of values(operation.parameters)) { - - if (parameter.name === 'api-version') { - // only set it if it hasn't been set yet. - // if (parameter.details.default.constantValue) { - //continue; - //} - - if (apiVersions) { - // set the constant value to the first one - if (length(apiVersions) === 1) { - parameter.details.default.constantValue = apiVersions[0]; - continue; - } - - // otherwise, the parameter can't have a constant value - parameter.details.default.constantValue = undefined; - - // mark it so that we can add profile support in the method generation - parameter.details.default.apiversion = true; - } - } - } - } - - // when make-sub-resources-byreference is specified, mark models with a writable id as byref. - if (await state.getValue('azure', false) && await state.getValue('make-sub-resources-byreference', false)) { - - for (const schema of values(model.schemas)) { - // find schemas that have an 'id' and are not readonly - if (values(getAllProperties(schema)).any(prop => prop.serializedName === 'id' && !prop.details.default.readOnly)) { - - // look thru the operations, and the PUT methods - for (const op of values(model.http.operations).where(o => o.method === HttpMethod.Put)) { - - // see if any of the responses have the same schema as we are looking for - if (values(op.responses).any(rsps => values(rsps).any(resp => !!resp.schema && resp.schema.details.default.uid === schema.details.default.uid))) { - - // tell it not to inline that - schema.details.default.byReference = true; - } - - } - } - } - } - - return model; -} - -// Azure version - -// Additional tweaks the code model to adjust things so that the code will generate better. - -export async function tweakModelAzurePlugin(service: Host) { - return processCodeModel(tweakModel, service, 'tweakcodemodelazure-v2'); -} diff --git a/powershell/plugins/powershell.ts b/powershell/plugins/powershell.ts deleted file mode 100644 index feffd74bee..0000000000 --- a/powershell/plugins/powershell.ts +++ /dev/null @@ -1,82 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { codemodel } from '@azure-tools/codemodel-v3'; -import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; -import { Host } from '@azure-tools/autorest-extension-base'; -import { join } from 'path'; -import { Project } from '../internal/project'; -import { State } from '../internal/state'; -import { generatePsm1 } from '../generators/psm1'; -import { generateCsproj } from '../generators/csproj'; -import { generatePsm1Custom } from '../generators/psm1.custom'; -import { generatePsm1Internal } from '../generators/psm1.internal'; -import { generateNuspec } from '../generators/nuspec'; -import { generateGitIgnore } from '../generators/gitignore'; -import { generateGitAttributes } from '../generators/gitattributes'; -import { generateReadme } from '../generators/readme'; -import { generateScriptCmdlets } from '../generators/script-cmdlet'; -import { NewProject } from '../internal/project'; - -const sourceFileCSharp = 'source-file-csharp'; -const resources = `${__dirname}/../../resources`; - - -async function copyRequiredFiles(project: Project | NewProject) { - const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; - - // Project assets - await copyResources(join(resources, 'assets'), async (fname, content) => project.state.writeFile(fname, content, undefined, 'source-file-other'), undefined, transformOutput); - - // Runtime files - await copyResources(join(resources, 'psruntime'), async (fname, content) => project.state.writeFile(join(project.runtimeFolder, fname), content, undefined, sourceFileCSharp), project.overrides, transformOutput); - - // Modules files - await copyBinaryResources(join(resources, 'modules'), async (fname, content) => project.state.writeFile(join(project.dependencyModuleFolder, fname), content, undefined, 'binary-file')); - - if (project.azure) { - // Signing key file - await copyBinaryResources(join(resources, 'signing'), async (fname, content) => project.state.writeFile(join(project.baseFolder, fname), content, undefined, 'binary-file')); - } -} - - -export async function powershell(service: Host) { - const debug = await service.GetValue('debug') || false; - - try { - const project = await new Project(service).init(); - - await project.writeFiles(async (filename, content) => project.state.writeFile(filename, applyOverrides(content, project.overrides), undefined, sourceFileCSharp)); - - await service.ProtectFiles(project.psd1); - await service.ProtectFiles(project.readme); - await service.ProtectFiles(project.customFolder); - await service.ProtectFiles(project.testFolder); - await service.ProtectFiles(project.docsFolder); - await service.ProtectFiles(project.examplesFolder); - await service.ProtectFiles(project.resourcesFolder); - - // wait for all the generation to be done - await copyRequiredFiles(project); - await generateCsproj(project); - await generatePsm1(project); - await generatePsm1Custom(project); - await generatePsm1Internal(project); - await generateNuspec(project); - await generateGitIgnore(project); - await generateGitAttributes(project); - await generateReadme(project); - - await generateScriptCmdlets(project); - - } catch (E) { - if (debug) { - console.error(`${__filename} - FAILURE ${JSON.stringify(E)} ${E.stack}`); - } - throw E; - } -} - diff --git a/powershell/plugins/ps-namer.ts b/powershell/plugins/ps-namer.ts deleted file mode 100644 index b01a9fce18..0000000000 --- a/powershell/plugins/ps-namer.ts +++ /dev/null @@ -1,201 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Host, Channel } from '@azure-tools/autorest-extension-base'; -import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames, ModelState, ParameterLocation, isMediaTypeMultipartFormData, VirtualParameter } from '@azure-tools/codemodel-v3'; -import { deconstruct, removeProhibitedPrefix, removeSequentialDuplicates, pascalCase } from '@azure-tools/codegen'; -import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import * as linq from '@azure-tools/linq'; -import { singularize } from '../internal/name-inferrer'; - -type State = ModelState; - -function getCmdletName(verb: string, subjectPrefix: string, subject: string): string { - return `${verb}-${subjectPrefix}${subject}`; -} - -export function getDeduplicatedNoun(subjectPrefix: string, subject: string): { subjectPrefix: string; subject: string } { - // dedup parts - const dedupedPrefix = [...removeSequentialDuplicates(deconstruct(subjectPrefix))]; - const dedupedSubject = [...removeSequentialDuplicates(deconstruct(subject))]; - - // dedup the noun - const dedupedMerge = [...removeSequentialDuplicates([...dedupedPrefix, ...dedupedSubject])]; - - // figure out what belongs to the subject - const reversedFinalSubject = new Array(); - for (let mCount = length(dedupedMerge) - 1, sCount = length(dedupedSubject) - 1; sCount >= 0 && mCount >= 0; mCount--, sCount--) { - if (dedupedMerge[mCount] !== dedupedSubject[sCount]) { - break; - } - - reversedFinalSubject.push(dedupedMerge.pop()); - } - - // what's left belongs to the prefix - const finalPrefix = new Array(); - for (const each of dedupedMerge) { - finalPrefix.push(each); - } - - return { subjectPrefix: pascalCase(finalPrefix), subject: pascalCase(reversedFinalSubject.reverse()) }; -} - -async function tweakModel(state: State): Promise { - // get the value - const isAzure = await state.getValue('azure', false); - // without setting snitize-names, isAzure is applied - const shouldSanitize = await state.getValue('sanitize-names', isAzure); - - // make sure recursively that every details field has csharp - for (const { index, instance } of linq.visitor(state.model)) { - if (index === 'details' && instance.default && !instance.csharp) { - instance.csharp = linq.clone(instance.default, false, undefined, undefined, ['schema', 'origin']); - } - } - // dolauli sanitize name - if (shouldSanitize) { - for (const operation of values(state.model.commands.operations)) { - // clean the noun (i.e. subjectPrefix + subject) - const prevSubjectPrefix = operation.details.csharp.subjectPrefix; - const prevSubject = operation.details.csharp.subject; - const dedupedNounParts = getDeduplicatedNoun(operation.details.csharp.subjectPrefix, operation.details.csharp.subject); - if (prevSubjectPrefix !== dedupedNounParts.subjectPrefix || prevSubject !== dedupedNounParts.subject) { - const verb = operation.details.csharp.verb; - const variantName = operation.details.csharp.name; - const prevCmdletName = getCmdletName(verb, prevSubjectPrefix, prevSubject); - operation.details.csharp.subjectPrefix = dedupedNounParts.subjectPrefix; - operation.details.csharp.subject = dedupedNounParts.subject; - const newCmdletName = getCmdletName(verb, operation.details.csharp.subjectPrefix, operation.details.csharp.subject); - state.message( - { - Channel: Channel.Debug, - Text: `Sanitized cmdlet-name -> Changed cmdlet-name from ${prevCmdletName} to ${newCmdletName}: {subjectPrefix: ${operation.details.csharp.subjectPrefix}, subject: ${operation.details.csharp.subject}${variantName ? `, variant: ${variantName}}` : '}'}` - } - ); - } - - const virtualParameters = [...allVirtualParameters(operation.details.csharp.virtualParameters)]; - for (const parameter of virtualParameters) { - let prevName = parameter.name; - const otherParametersNames = values(virtualParameters) - .select(each => each.name) - .where(name => name !== parameter.name) - .toArray(); - - // first try to singularize the parameter - const singularName = singularize(parameter.name); - if (prevName != singularName) { - parameter.name = singularName; - state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to singular ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); - } - - // save the name again to compare in case it was modified - prevName = parameter.name; - - // now remove the subject from the beginning of the parameter - // to reduce naming redundancy, but just for path parameters - // e.g. get-vm -vmname ---> get-vm -name - if ((parameter.origin).in === ParameterLocation.Path) { - const sanitizedName = removeProhibitedPrefix( - parameter.name, - operation.details.csharp.subject, - otherParametersNames - ); - - if (prevName !== sanitizedName) { - if (parameter.alias === undefined) { - parameter.alias = []; - } - - // saved the prev name as alias - parameter.alias.push(parameter.name); - - // change name - parameter.name = sanitizedName; - state.message({ Channel: Channel.Debug, Text: `Sanitized parameter-name -> Changed parameter-name from ${prevName} to ${parameter.name} from command ${operation.verb}-${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}` }); - state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); - } - } - } - } - - for (const schema of values(state.model.schemas)) { - const virtualProperties = [...allVirtualProperties(schema.details.csharp.virtualProperties)]; - - for (const property of virtualProperties) { - let prevName = property.name; - const otherPropertiesNames = values(virtualProperties) - .select(each => each.name) - .where(name => name !== property.name) - .toArray(); - - // first try to singularize the property - const singularName = singularize(property.name); - if (prevName != singularName) { - property.name = singularName; - state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to singular ${property.name} from model ${schema.details.csharp.name}` }); - } - - // save the name again to compare in case it was modified - prevName = property.name; - - // now remove the model=name from the beginning of the property-name - // to reduce naming redundancy - const sanitizedName = removeProhibitedPrefix( - property.name, - schema.details.csharp.name, - otherPropertiesNames - ); - - if (prevName !== sanitizedName) { - property.alias = property.alias || []; - - // saved the prev name as alias - property.alias.push(property.name); - - // change name - property.name = sanitizedName; - state.message({ Channel: Channel.Debug, Text: `Sanitized property-name -> Changed property-name from ${prevName} to ${property.name} from model ${schema.details.csharp.name}` }); - state.message({ Channel: Channel.Debug, Text: ` -> And, added alias '${prevName}'` }); - - // update shared properties too - if (property.sharedWith) { - for (const sharedProperty of property.sharedWith) { - if (sharedProperty.name !== sanitizedName) { - state.message({ Channel: Channel.Debug, Text: `Changing shared property ${sharedProperty.name} to ${sanitizedName}` }); - sharedProperty.alias = sharedProperty.alias || []; - sharedProperty.alias.push(sharedProperty.name); - sharedProperty.name = sanitizedName; - } - } - } - } - } - } - } - - // do collision detection work. - for (const command of values(state.model.commands.operations)) { - const vp = command.details.csharp.virtualParameters; - if (vp) { - resolveParameterNames([], vp); - } - } - - for (const schema of values(state.model.schemas)) { - const vp = schema.details.csharp.virtualProperties; - if (vp) { - resolvePropertyNames([schema.details.csharp.name], vp); - } - } - return state.model; -} - - -export async function namer(service: Host) { - // dolauli add csharp for cmdlets in the command->operation node - return processCodeModel(tweakModel, service, 'psnamer'); -} \ No newline at end of file diff --git a/powershell/test/noun-cleaning.ts b/powershell/test/noun-cleaning.ts index 0a6374f5aa..11e6cd28ff 100644 --- a/powershell/test/noun-cleaning.ts +++ b/powershell/test/noun-cleaning.ts @@ -5,7 +5,7 @@ import { suite, test } from 'mocha-typescript'; import * as assert from 'assert'; -import { getDeduplicatedNoun } from '../plugins/ps-namer'; +import { getDeduplicatedNoun } from '../plugins/ps-namer-v2'; @suite class TestNounCleaning { diff --git a/powershell/test/operationId-inferring.ts b/powershell/test/operationId-inferring.ts index 981d69c548..c2adcfee19 100644 --- a/powershell/test/operationId-inferring.ts +++ b/powershell/test/operationId-inferring.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { suite, test } from 'mocha-typescript'; -import * as pp from '../plugins/create-commands'; +import * as pp from '../plugins/create-commands-v2'; import { ModelState, JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, } from '@azure-tools/codemodel-v3'; import { Channel, JsonPath, Mapping, RawSourceMap, Message } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; diff --git a/powershell/test/test-service-name.ts b/powershell/test/test-service-name.ts index 02ca436459..5e780faae7 100644 --- a/powershell/test/test-service-name.ts +++ b/powershell/test/test-service-name.ts @@ -7,7 +7,7 @@ import { suite, test } from 'mocha-typescript'; import * as assert from 'assert'; import * as aio from '@azure-tools/async-io'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { titleToAzureServiceName } from '../plugins/create-commands'; +import { titleToAzureServiceName } from '../plugins/create-commands-v2'; @suite class TestServiceName { From 61544061e62583377a5ef30d5f6ac44be493ef8a Mon Sep 17 00:00:00 2001 From: derek Date: Thu, 15 Oct 2020 16:26:40 +0800 Subject: [PATCH 3/5] clean code used by m3 generator --- powershell/cmdlets/class.ts | 1220 +---------------- powershell/cmdlets/namespace.ts | 30 +- powershell/enums/namespace.ts | 113 +- powershell/generators/csproj.ts | 3 +- powershell/generators/gitattributes.ts | 4 +- powershell/generators/gitignore.ts | 4 +- powershell/generators/nuspec.ts | 4 +- powershell/generators/psm1.custom.ts | 4 +- powershell/generators/psm1.internal.ts | 4 +- powershell/generators/psm1.ts | 4 +- powershell/generators/readme.ts | 4 +- powershell/generators/script-cmdlet.ts | 5 +- powershell/internal/project.ts | 197 +-- powershell/internal/state.ts | 33 +- powershell/llcsharp/code-model.ts | 10 +- powershell/llcsharp/enums/enum.ts | 165 +-- powershell/llcsharp/enums/json-serializer.ts | 48 - powershell/llcsharp/enums/namespace.ts | 4 +- powershell/llcsharp/generator.ts | 32 +- powershell/llcsharp/model/interface.ts | 157 +-- .../llcsharp/model/model-class-dictionary.ts | 108 +- powershell/llcsharp/model/model-class-json.ts | 216 +-- .../llcsharp/model/model-class-serializer.ts | 111 +- powershell/llcsharp/model/model-class-xml.ts | 174 --- powershell/llcsharp/model/model-class.ts | 487 +------ powershell/llcsharp/model/namespace.ts | 140 +- powershell/llcsharp/model/property.ts | 69 +- powershell/llcsharp/operation/api-class.ts | 57 +- powershell/llcsharp/operation/method.ts | 741 +--------- powershell/llcsharp/operation/namespace.ts | 6 +- powershell/llcsharp/operation/parameter.ts | 140 +- powershell/llcsharp/project.ts | 85 +- powershell/llcsharp/schema/schema-resolver.ts | 132 +- powershell/llcsharp/validations.ts | 10 +- powershell/models/model-extensions.ts | 240 +--- powershell/module/module-class.ts | 285 +--- powershell/module/module-namespace.ts | 23 +- powershell/plugins/add-azure-completers-v2.ts | 6 +- powershell/plugins/create-commands-v2.ts | 7 +- powershell/plugins/cs-namer-v2.ts | 9 +- powershell/plugins/llcsharp-v2.ts | 3 +- powershell/plugins/modifiers-v2.ts | 7 +- .../plugin-create-inline-properties.ts | 6 +- powershell/plugins/plugin-tweak-m4-model.ts | 6 +- .../plugins/plugin-tweak-model-azure-v2.ts | 6 +- powershell/plugins/plugin-tweak-model.ts | 8 +- powershell/plugins/powershell-v2.ts | 3 +- powershell/plugins/ps-namer-v2.ts | 6 +- powershell/test/operationId-inferring.ts | 1 - powershell/utils/PwshModel.ts | 1 - powershell/utils/model-state.ts | 6 +- 51 files changed, 225 insertions(+), 4919 deletions(-) delete mode 100644 powershell/llcsharp/enums/json-serializer.ts delete mode 100644 powershell/llcsharp/model/model-class-xml.ts diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index efe286423d..3a4cb6b964 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -15,12 +15,12 @@ import { } from '@azure-tools/codegen-csharp'; import { ClientRuntime, EventListener, Schema, ArrayOf, NewArrayOf, EnumImplementation, NewEnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; -import { State, NewState } from '../internal/state'; +import { NewState } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; import { IParameter } from '@azure-tools/codemodel-v3/dist/code-model/components'; import { IParameter as NewIParameter } from '../utils/components'; import { Variable, Local, ParameterModifier } from '@azure-tools/codegen-csharp'; -import { getVirtualPropertyName } from '../llcsharp/model/model-class'; +import { NewGetVirtualPropertyName } from '../llcsharp/model/model-class'; const PropertiesRequiringNew = new Set(['Host', 'Events']); @@ -287,1216 +287,6 @@ export function NewAddInfoAttribute(targetProperty: Property, pType: TypeDeclara } -export class CmdletClass extends Class { - private cancellationToken!: Expression; - public state: State; - private readonly eventListener: EventListener; - private readonly dropBodyParameter: boolean; - private invocationInfo!: Property; - correlationId!: Field; - processRecordId!: Field; - defaultProfile!: Property; - private readonly thingsToSerialize: Array; - private bodyParameter?: Variable; - private bodyParameterInfo?: { type: TypeDeclaration; valueType: TypeDeclaration }; - private apProp?: Property; - private operation: command.CommandOperation; - private debugMode?: boolean; - private variantName: string; - private isViaIdentity: boolean; - private hasStreamOutput: boolean; - private outFileParameter?: Property; - - constructor(namespace: Namespace, operation: command.CommandOperation, state: State, objectInitializer?: DeepPartial) { - // generate the 'variant' part of the name - const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; - const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; - - const name = `${operation.details.csharp.verb}${variantName}`; - super(namespace, name, PSCmdlet); - this.dropBodyParameter = operation.details.csharp.dropBodyParameter ? true : false; - this.apply(objectInitializer); - this.operation = operation; - this.state = state; - this.thingsToSerialize = []; - this.variantName = variantName; - this.hasStreamOutput = false; - - this.interfaces.push(ClientRuntime.IEventListener); - this.eventListener = new EventListener(new LiteralExpression(`((${ClientRuntime.IEventListener})this)`), true); - - this.isViaIdentity = variantName.indexOf('ViaIdentity') > 0; - - } - - async init() { - - // basic stuff - this.addCommonStuff(); - - this.description = escapeString(this.operation.details.csharp.description); - const $this = this; - - this.add(new Method('BeginProcessing', dotnet.Void, { - override: Modifier.Override, - access: Access.Protected, - description: `(overrides the default BeginProcessing method in ${PSCmdlet})`, - *body() { - yield 'Module.Instance.SetProxyConfiguration(Proxy, ProxyCredential, ProxyUseDefaultCredentials);'; - yield If($this.$('Break'), `${ClientRuntime.AttachDebugger}.Break();`); - - yield $this.eventListener.syncSignal(Events.CmdletBeginProcessing); - } - })); - - // construct the class - this.addClassAttributes(this.operation, this.variantName); - if (this.hasStreamOutput) { - this.outFileParameter = this.add(new Property('OutFile', System.String, { attributes: [], description: 'Path to write output file to.' })); - this.outFileParameter.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = true', 'HelpMessage = "Path to write output file to"'] })); - this.outFileParameter.add(new Attribute(ValidateNotNull)); - this.outFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - } - - this.addPowershellParameters(this.operation); - - // implement IEventListener - this.implementIEventListener(); - - // add constructors - this.implementConstructors(); - - // processRecord - this.implementProcessRecord(this.operation); - - this.implementProcessRecordAsync(this.operation); - this.debugMode = await this.state.getValue('debug', false); - - // json serialization - this.implementSerialization(this.operation); - - for (const prop of this.properties) { - if (prop.name === 'Host') { - prop['new'] = Modifier.New; - } - } - - return this; - } - - public get headerComment(): string { - const header = super.headerComment; - let ops = ''; - - for (const httpOperation of values(this.operation.callGraph)) { - ops = `${ops}\n[OpenAPI] ${httpOperation.operationId}=>${httpOperation.method.toUpperCase()}:"${httpOperation.path}"`; - if (this.debugMode) { - const m = (httpOperation.extensions && httpOperation.extensions['x-ms-metadata']) || (httpOperation.pathExtensions ? httpOperation.pathExtensions['x-ms-metadata'] : undefined); - if (m) { - ops = `${ops}\n [METADATA]\n${serialize(m)}`; - } - - ops = `${ops}\n [DETAILS]`; - ops = `${ops}\n verb: ${this.operation.details.csharp.verb}`; - ops = `${ops}\n subjectPrefix: ${this.operation.details.csharp.subjectPrefix}`; - ops = `${ops}\n subject: ${this.operation.details.csharp.subject}`; - ops = `${ops}\n variant: ${this.operation.details.csharp.name}`; - } - } - - return ops ? `${header}\n${docComment(xmlize('remarks', ops))}` : header; - } - - private addCommonStuff() { - - // add a private copy of invocation information for our own uses. - const privateInvocationInfo = this.add(new Field('__invocationInfo', InvocationInfo, { description: 'A copy of the Invocation Info (necessary to allow asJob to clone this cmdlet)', access: Access.Private })); - this.invocationInfo = new Property('InvocationInformation', InvocationInfo, { description: 'Accessor for our copy of the InvocationInfo.' }); - this.invocationInfo.get = toExpression(`${privateInvocationInfo.value} = ${privateInvocationInfo.value} ?? this.MyInvocation `); - this.invocationInfo.set = new Statements(privateInvocationInfo.assign('value')); - this.add(this.invocationInfo); - - if (this.state.project.azure) { - this.correlationId = this.add(new Field('__correlationId', dotnet.String, { initialValue: 'System.Guid.NewGuid().ToString()', description: 'A unique id generatd for the this cmdlet when it is instantiated.', access: Access.Private })); - this.processRecordId = this.add(new Field('__processRecordId', dotnet.String, { description: 'A unique id generatd for the this cmdlet when ProcessRecord() is called.', access: Access.Private })); - } - - // pipeline property - this.add(new Property('Pipeline', ClientRuntime.HttpPipeline, { getAccess: Access.Private, setAccess: Access.Private, description: `The instance of the that the remote call will use.` })); - - // client API property (gs01: fill this in correctly) - const clientAPI = new ClassType(this.state.model.details.csharp.namespace, this.state.model.details.csharp.name); - this.add(new LambdaProperty('Client', clientAPI, new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.ClientAPI`), { description: 'The reference to the client API class.' })); - - this.add(new Method('StopProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Interrupts currently running code within the command.' })).add(function* () { - yield `((${ClientRuntime.IEventListener})this).Cancel();`; - yield 'base.StopProcessing();'; - }); - - const $this = this; - this.add(new Method('EndProcessing', dotnet.Void, { access: Access.Protected, override: Modifier.Override, description: 'Performs clean-up after the command execution' })).add(function* () { - // gs01: remember what you were doing here to make it so these can be parallelized... - yield ''; - yield $this.eventListener.syncSignal(Events.CmdletEndProcessing); - }); - - // debugging - const brk = this.add(new Property('Break', SwitchParameter, { attributes: [], description: 'Wait for .NET debugger to attach' })); - brk.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Wait for .NET debugger to attach"'] })); - brk.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - // Cmdlet Parameters for pipeline manipulations. - const prepend = this.add(new Property('HttpPipelinePrepend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be prepended to the front of the pipeline' })); - prepend.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be prepended to the front of the pipeline"'] })); - prepend.add(new Attribute(ValidateNotNull)); - prepend.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const append = this.add(new Property('HttpPipelineAppend', ClientRuntime.SendAsyncSteps, { attributes: [], description: 'SendAsync Pipeline Steps to be appended to the front of the pipeline' })); - append.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "SendAsync Pipeline Steps to be appended to the front of the pipeline"'] })); - append.add(new Attribute(ValidateNotNull)); - append.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const proxyCredential = this.add(new Property('ProxyCredential', PSCredential, { attributes: [], description: 'Credentials for a proxy server to use for the remote call' })); - proxyCredential.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Credentials for a proxy server to use for the remote call"'] })); - proxyCredential.add(new Attribute(ValidateNotNull)); - proxyCredential.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const useDefaultCreds = this.add(new Property('ProxyUseDefaultCredentials ', SwitchParameter, { attributes: [], description: 'Use the default credentials for the proxy' })); - useDefaultCreds.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "Use the default credentials for the proxy"'] })); - useDefaultCreds.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const proxyUri = this.add(new Property('Proxy', System.Uri, { attributes: [], description: 'The URI for the proxy server to use' })); - proxyUri.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'DontShow = true', 'HelpMessage = "The URI for the proxy server to use"'] })); - proxyUri.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - if (this.state.project.azure) { - this.defaultProfile = this.add(new Property('DefaultProfile', PSObject, { description: 'The credentials, account, tenant, and subscription used for communication with Azure' })); - this.defaultProfile.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "The credentials, account, tenant, and subscription used for communication with Azure."'] })); - this.defaultProfile.add(new Attribute(ValidateNotNull)); - this.defaultProfile.add(new Attribute(Alias, { parameters: ['"AzureRMContext"', '"AzureCredential"'] })); - this.defaultProfile.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Azure`] })); - } - } - - private isWritableCmdlet(operation: command.CommandOperation): boolean { - switch (operation.callGraph[0].method.toLowerCase()) { - case 'put': - case 'post': - case 'delete': - case 'patch': - return true; - } - return false; - } - - private implementProcessRecord(operation: command.CommandOperation) { - const $this = this; - const writable = this.isWritableCmdlet(operation); - - this.add(new Method('ProcessRecord', undefined, { access: Access.Protected, override: Modifier.Override, description: 'Performs execution of the command.' })).add(function* () { - yield $this.eventListener.syncSignal(Events.CmdletProcessRecordStart); - if ($this.state.project.azure) { - yield $this.processRecordId.assign('System.Guid.NewGuid().ToString()'); - } - yield Try(function* () { - yield '// work'; - const normal = new Statements(function* () { - const acr = new LocalVariable('asyncCommandRuntime', dotnet.Var, { initializer: AsyncCommandRuntime.new(dotnet.This, $this.cancellationToken) }); - yield Using(acr.declarationExpression, function* () { - yield `${acr}.Wait( ProcessRecordAsync(),${$this.cancellationToken});`; - }); - }); - - if (operation.asjob) { - const asjob = $this.add(new Property('AsJob', SwitchParameter, { description: 'when specified, runs this cmdlet as a PowerShell job' })); - asjob.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command as a job"'] })); - asjob.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - const nowait = $this.add(new Property('NoWait', SwitchParameter, { description: 'when specified, will make the remote call, and return an AsyncOperationResponse, letting the remote operation continue asynchronously.' })); - nowait.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Run the command asynchronously"'] })); - nowait.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - - } - - const work: OneOrMoreStatements = operation.asjob ? function* () { - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("AsJob")', function* () { - // clone the cmdlet instance, since the instance can be reused and overwrite data. - const instance = new LocalVariable('instance', dotnet.Var, { initializer: 'this.Clone()' }); - yield instance.declarationStatement; - - // create the job (which will set the CommandRuntime of the clone to the AsyncJob itself) - const job = new LocalVariable('job', dotnet.Var, { initializer: AsyncJob.new(instance, 'this.MyInvocation.Line, this.MyInvocation.MyCommand.Name, this._cancellationTokenSource.Token', 'this._cancellationTokenSource.Cancel') }); - yield job.declarationStatement; - - // add the job to the repository - yield `JobRepository.Add(${job});`; - - // invoke the cmdlet's PRA - const task = new LocalVariable('task', dotnet.Var, { initializer: `${instance}.ProcessRecordAsync()` }); - yield task.declarationStatement; - - // have the AsyncJob monitor the lifetime of the Task - yield `${job}.Monitor(${task});`; - - // return the job to the user now. - yield `WriteObject(${job});`; - - }); - yield Else(normal); - } : normal; - - if (writable) { - yield If(`ShouldProcess($"Call remote '${operation.callGraph[0].details.csharp.name}' operation")`, work); - } else { - yield work; - } - }); - const aggregateException = new Parameter('aggregateException', System.AggregateException); - yield Catch(aggregateException, function* () { - yield '// unroll the inner exceptions to get the root cause'; - yield ForEach('innerException', new LiteralExpression(`${aggregateException.use}.Flatten().InnerExceptions`), function* () { - yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression('$"{innerException.GetType().Name} - {innerException.Message} : {innerException.StackTrace}"')); - yield '// Write exception out to error channel.'; - yield `WriteError( new ${ErrorRecord}(innerException,string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; - }); - }); - const exception = new Parameter('exception', System.Exception); - yield Catch(exception, function* () { - yield $this.eventListener.syncSignal(Events.CmdletException, new LiteralExpression(`$"{${exception.use}.GetType().Name} - {${exception.use}.Message} : {${exception.use}.StackTrace}"`)); - yield '// Write exception out to error channel.'; - yield `WriteError( new ${ErrorRecord}(${exception.use},string.Empty, ${ErrorCategory('NotSpecified')}, null) );`; - }, { when: new LiteralExpression('(exception as System.Management.Automation.PipelineStoppedException)== null || (exception as System.Management.Automation.PipelineStoppedException).InnerException != null') }); - - yield Finally(function* () { - yield $this.eventListener.syncSignalNoCheck(Events.CmdletProcessRecordEnd); - }); - }); - - } - - private implementProcessRecordAsync(operation: command.CommandOperation) { - const $this = this; - const PAR = this.add(new Method('ProcessRecordAsync', System.Threading.Tasks.Task(), { - access: Access.Protected, async: Modifier.Async, - description: 'Performs execution of the command, working asynchronously if required.', - returnsDescription: `A that will be complete when handling of the method is completed.` - })); - - // we don't want to use SynchContext here. - PAR.push(Using('NoSynchronizationContext', '')); - - PAR.add(function* () { - if ($this.apProp && $this.bodyParameter && $this.bodyParameterInfo) { - // yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${$this.bodyParameterInfo.type.declaration},${$this.bodyParameterInfo.valueType.declaration}>(${$this.apProp.value},${$this.bodyParameter.Cast($this.bodyParameterInfo.type)});`; - let vt = $this.bodyParameterInfo.valueType.declaration; - if (vt.endsWith('SwitchParameter')) { - vt = 'bool'; - } - yield `${ClientRuntime}.DictionaryExtensions.HashTableToDictionary<${vt}>(${$this.apProp.value},${$this.bodyParameter}.AdditionalProperties);`; - } - - // construct the call to the operation - yield $this.eventListener.signal(Events.CmdletProcessRecordAsyncStart); - - yield $this.eventListener.signal(Events.CmdletGetPipeline); - - const pipeline = $this.$('Pipeline'); - - if ($this.state.project.azure) { - yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, ${$this.correlationId}, ${$this.processRecordId}, this.ParameterSetName)`)); - } else { - yield pipeline.assign(new LiteralExpression(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.CreatePipeline(${$this.invocationInfo}, this.ParameterSetName)`)); - } - - yield If(IsNotNull($this.$('HttpPipelinePrepend')), pipeline.invokeMethod('Prepend', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelinePrepend')}) ?? ${$this.$('HttpPipelinePrepend')}`))); - yield If(IsNotNull($this.$('HttpPipelineAppend')), pipeline.invokeMethod('Append', toExpression(`(this.CommandRuntime as Microsoft.Rest.ClientRuntime.PowerShell.IAsyncCommandRuntimeExtensions)?.Wrap(${$this.$('HttpPipelineAppend')}) ?? ${$this.$('HttpPipelineAppend')}`))); - - yield '// get the client instance'; - const apiCall = operation.callGraph[0]; - - // find each parameter to the method, and find out where the value is going to come from. - const operationParameters = - values(apiCall.parameters). - // filter out constants and path parameters when using piping for identity - where(each => !(each.details.csharp.constantValue) /* && (!$this.isViaIdentity || each.in !== ParameterLocation.Path) */). - - select(p => { - return { - name: p.details.csharp.name, - param: values($this.properties). - where(each => each.metadata.parameterDefinition). - first(each => each.metadata.parameterDefinition.details.csharp.uid === p.details.csharp.uid), - isPathParam: $this.isViaIdentity && p.in === ParameterLocation.Path - }; - - }). - select(each => { - if (each.param) { - - const httpParam = ((each.param.metadata.parameterDefinition)); - if (httpParam.required) { - return { - name: each.param, - expression: each.param, - isPathParam: each.isPathParam - }; - } - - const httpParamTD = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((httpParam.schema), httpParam.required, $this.state); - return { - name: each.param, - expression: toExpression(`this.InvocationInformation.BoundParameters.ContainsKey("${each.param.value}") ? ${each.param.value} : ${httpParamTD.defaultOfType}`), - isPathParam: each.isPathParam - }; - - } - - return { name: each.name, expression: dotnet.Null, isPathParam: each.isPathParam }; - }).toArray(); - - // is there a body parameter we should include? - if ($this.bodyParameter) { - operationParameters.push({ name: 'body', expression: $this.bodyParameter, isPathParam: false }); - } - - // create the response handlers - const responses = [...values(apiCall.responses).selectMany(each => each)]; - - const callbackMethods = values(responses).toArray().map(each => new LiteralExpression(each.details.csharp.name)); - - // make callback methods - for (const each of values(responses)) { - - const parameters = new Array(); - parameters.push(new Parameter('responseMessage', System.Net.Http.HttpResponseMessage, { description: `the raw response message as an ${System.Net.Http.HttpResponseMessage}.` })); - - if (each.details.csharp.responseType) { - parameters.push(new Parameter('response', System.Threading.Tasks.Task({ declaration: each.details.csharp.responseType }), { description: `the body result as a from the remote call` })); - } - if (each.details.csharp.headerType) { - parameters.push(new Parameter('headers', System.Threading.Tasks.Task({ declaration: each.details.csharp.headerType }), { description: `the header result as a from the remote call` })); - } - - const override = `override${pascalCase(each.details.csharp.name)}`; - const returnNow = new Parameter('returnNow', System.Threading.Tasks.Task(dotnet.Bool), { modifier: ParameterModifier.Ref, description: `/// Determines if the rest of the ${each.details.csharp.name} method should be processed, or if the method should return immediately (set to true to skip further processing )` }); - const overrideResponseMethod = new PartialMethod(override, dotnet.Void, { - parameters: [...parameters, returnNow], - description: `${override} will be called before the regular ${each.details.csharp.name} has been processed, allowing customization of what happens on that response. Implement this method in a partial class to enable this behavior`, - returnsDescription: `A that will be complete when handling of the method is completed.` - }); - $this.add(overrideResponseMethod); - - const responseMethod = new Method(`${each.details.csharp.name}`, System.Threading.Tasks.Task(), { - access: Access.Private, - parameters, - async: Modifier.Async, - description: each.details.csharp.description, - returnsDescription: `A that will be complete when handling of the method is completed.` - }); - responseMethod.push(Using('NoSynchronizationContext', '')); - - - responseMethod.add(function* () { - const skip = Local('_returnNow', `${System.Threading.Tasks.Task(dotnet.Bool).declaration}.FromResult(${dotnet.False})`); - yield skip.declarationStatement; - yield `${overrideResponseMethod.invoke(...parameters, `ref ${skip.value}`)};`; - yield `// if ${override} has returned true, then return right away.`; - yield If(And(IsNotNull(skip), `await ${skip}`), Return()); - - if (each.details.csharp.isErrorResponse) { - // this should write an error to the error channel. - yield `// Error Response : ${each.responseCode}`; - - - const unexpected = function* () { - yield '// Unrecognized Response. Create an error record based on what we have.'; - const ex = (each.details.csharp.responseType) ? - Local('ex', `new ${ClientRuntime.name}.RestException<${each.details.csharp.responseType}>(responseMessage, await response)`) : - Local('ex', `new ${ClientRuntime.name}.RestException(responseMessage)`); - - yield ex.declarationStatement; - - yield `WriteError( new global::System.Management.Automation.ErrorRecord(${ex.value}, ${ex.value}.Code, global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ex.value}.Message) { RecommendedAction = ${ex.value}.Action } -});`; - }; - if (each.schema) { - // the schema should be the error information. - // this supports both { error { message, code} } and { message, code} - - let props = getAllPublicVirtualProperties(each.schema.details.csharp.virtualProperties); - const errorProperty = values(props).first(p => p.property.details.csharp.name === 'error'); - let ep = ''; - if (errorProperty) { - props = getAllPublicVirtualProperties(errorProperty.property.schema.details.csharp.virtualProperties); - ep = `${errorProperty.name}?.`; - } - - const codeProp = props.find(p => p.name.toLowerCase().indexOf('code') > -1); // first property with 'code' - const messageProp = props.find(p => p.name.toLowerCase().indexOf('message') > -1); // first property with 'message' - const actionProp = props.find(p => p.name.toLowerCase().indexOf('action') > -1); // first property with 'action' - - if (codeProp && messageProp) { - const lcode = new LocalVariable('code', dotnet.Var, { initializer: `(await response)?.${ep}${codeProp.name}` }); - const lmessage = new LocalVariable('message', dotnet.Var, { initializer: `(await response)?.${ep}${messageProp.name}` }); - const laction = actionProp ? new LocalVariable('action', dotnet.Var, { initializer: `(await response)?.${ep}${actionProp.name} ?? ${System.String.Empty}` }) : undefined; - yield lcode; - yield lmessage; - yield laction; - - yield If(Or(IsNull(lcode), (IsNull(lmessage))), unexpected); - yield Else(`WriteError( new global::System.Management.Automation.ErrorRecord(new global::System.Exception($"[{${lcode}}] : {${lmessage}}"), ${lcode}?.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(', ')} }) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${lmessage}) { RecommendedAction = ${laction || System.String.Empty} } -});` - - ); - return; - } else { - yield unexpected; - return; - } - } else { - yield unexpected; - return; - } - } - - yield `// ${each.details.csharp.name} - response for ${each.responseCode} / ${values(each.mimeTypes).join('/')}`; - if (each.schema) { - const schema = each.schema; - - if (apiCall.details.csharp.pageable) { - const pageable = apiCall.details.csharp.pageable; - yield '// response should be returning an array of some kind. +Pageable'; - yield `// ${pageable.responseType} / ${pageable.itemName || ''} / ${pageable.nextLinkName || ''}`; - switch (pageable.responseType) { - // the result is (or works like a x-ms-pageable) - case 'pageable': - case 'nested-array': { - const valueProperty = schema.properties[pageable.itemName]; - const nextLinkProperty = schema.properties[pageable.nextLinkName]; - if (valueProperty && nextLinkProperty) { - // it's pageable! - const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('await response') }); - yield result.declarationStatement; - // write out the current contents - const vp = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - if (vp) { - yield `WriteObject(${result.value}.${vp.name},true);`; - } - const nl = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, nextLinkProperty.serializedName); - if (nl) { - const nextLinkName = `${result.value}.${nl.name}`; - yield (If(`${nextLinkName} != null`, - If('responseMessage.RequestMessage is System.Net.Http.HttpRequestMessage requestMessage ', function* () { - yield `requestMessage = requestMessage.Clone(new global::System.Uri( ${nextLinkName} ),${ClientRuntime.Method.Get} );`; - yield $this.eventListener.signal(Events.FollowingNextLink); - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}_Call`, ...[toExpression('requestMessage'), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - }) - )); - } - return; - } else if (valueProperty) { - // it's just a nested array - const p = getVirtualPropertyFromPropertyName(each.schema.details.csharp.virtualProperties, valueProperty.serializedName); - if (p) { - yield `WriteObject((await response).${p.name}, true);`; - } - return; - } - } - break; - - // it's just an array, - case 'array': - // just write-object(enumerate) with the output - yield 'WriteObject(await response, true);'; - return; - } - // ok, let's see if the response type - } - const props = getAllPublicVirtualProperties(schema.details.csharp.virtualProperties); - const outValue = (length(props) === 1) ? `(await response).${props[0].name}` : '(await response)'; - - - // we expect to get back some data from this call. - - const rType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(schema, true, $this.state); - yield `// (await response) // should be ${rType.declaration}`; - if ($this.hasStreamOutput && $this.outFileParameter) { - const outfile = $this.outFileParameter; - const provider = Local('provider'); - provider.initializer = undefined; - const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(${outfile.value}, out ${provider.declarationExpression})`); - yield paths.declarationStatement; - yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid output path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); - yield If(`${paths.value}.Count > 1`, `ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple output paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, ${outfile.value}) );`); - - if (rType.declaration === System.IO.Stream.declaration) { - // this is a stream output. write to outfile - const stream = Local('stream', 'await response'); - yield Using(stream.declarationExpression, function* () { - const fileStream = Local('fileStream', `global::System.IO.File.OpenWrite(${paths.value}[0])`); - yield Using(fileStream.declarationExpression, `await ${stream.value}.CopyToAsync(${fileStream.value});`); - }); - } else { - // assuming byte array output (via outValue) - yield `global::System.IO.File.WriteAllBytes(${paths.value}[0],${outValue});`; - } - - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { - // no return type. Let's just return ... true? - yield 'WriteObject(true);'; - }); - return; - } - - // let's just return the result object (or unwrapped result object) - yield `WriteObject(${outValue});`; - return; - } - - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("PassThru")', function* () { - // no return type. Let's just return ... true? - yield 'WriteObject(true);'; - }); - }); - $this.add(responseMethod); - } - - yield Try(function* () { - // make the call. - - const actualCall = function* () { - yield $this.eventListener.signal(Events.CmdletBeforeAPICall); - const idOpParams = operationParameters.filter(each => !each.isPathParam); - const idschema = values($this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - - - if ($this.isViaIdentity) { - const identityFromPathParams = function* () { - yield '// try to call with PATH parameters from Input Object'; - - if (idschema) { - const allVPs = getAllPublicVirtualProperties(idschema.details.csharp.virtualProperties); - const props = [...values(idschema.properties)]; - - const idOpParams = operationParameters.map(each => { - const pascalName = pascalCase(`${each.name}`); - - if (!each.isPathParam) { - return { - name: undefined, - value: valueOf(each.expression) - }; - } - const match = props.find(p => pascalCase(p.serializedName) === pascalName); - if (match) { - - const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType; - // match up vp name - const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName); - if (vp) { - return { - name: `InputObject.${vp.name}`, - value: `InputObject.${vp.name} ?? ${defaultOfType}` - }; - } - // fall back! - - console.error(`Unable to match identity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalCase(match.details.csharp.name)}').`); - return { - name: `InputObject.${pascalCase(match.details.csharp.name)}`, - value: `InputObject.${pascalCase(match.details.csharp.name)} ?? ${defaultOfType}` - }; - } - console.error(`Unable to match idenity parameter '${each.name}' member to appropriate virtual parameter. (Guessing '${pascalName}')`); - return { - name: `InputObject.${pascalName}`, - value: `InputObject.${pascalName}` - }; - }); - for (const opParam of idOpParams) { - if (opParam.name) { - yield If(IsNull(opParam.name), `ThrowTerminatingError( new ${ErrorRecord}(new global::System.Exception("InputObject has null value for ${opParam.name}"),string.Empty, ${ErrorCategory('InvalidArgument')}, InputObject) );`); - } - } - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...idOpParams.map(each => toExpression(each.value)), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - - } - }; - - if (idschema && values(idschema.properties).first(each => each.details.csharp.uid === 'universal-parameter:resource identity')) { - yield If('InputObject?.Id != null', `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}ViaIdentity`, ...[toExpression('InputObject.Id'), ...idOpParams.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`); - yield Else(identityFromPathParams); - } else { - yield identityFromPathParams; - } - } else { - yield `await this.${$this.$('Client').invokeMethod(`${apiCall.details.csharp.name}`, ...[...operationParameters.map(each => each.expression), ...callbackMethods, dotnet.This, pipeline]).implementation}`; - } - yield $this.eventListener.signal(Events.CmdletAfterAPICall); - }; - - if ($this.state.project.azure && operationParameters.find(each => each.expression && each.expression.value === 'SubscriptionId') && $this.operation.details.csharp.verb.toLowerCase() === 'get') { - yield 'foreach( var SubscriptionId in this.SubscriptionId )'; - yield BlockStatement(actualCall); - } else { - yield actualCall; - } - }); - const ure = new Parameter('urexception', { declaration: `${ClientRuntime.fullName}.UndeclaredResponseException` }); - yield Catch(ure, function* () { - yield `WriteError(new global::System.Management.Automation.ErrorRecord(${ure.value}, ${ure.value}.StatusCode.ToString(), global::System.Management.Automation.ErrorCategory.InvalidOperation, new { ${operationParameters.filter(e => valueOf(e.expression) !== 'null').map(each => `${each.name}=${each.expression}`).join(',')}}) -{ - ErrorDetails = new global::System.Management.Automation.ErrorDetails(${ure.value}.Message) { RecommendedAction = ${ure.value}.Action } -});`; - }); - yield Finally(function* () { - yield $this.eventListener.signalNoCheck(Events.CmdletProcessRecordAsyncEnd); - }); - }); - } - - private implementSerialization(operation: command.CommandOperation) { - const $this = this; - // clone - if (operation.asjob) { - const clone = this.add(new Method('Clone', this, { - description: 'Creates a duplicate instance of this cmdlet (via JSON serialization).', - returnsDescription: `a duplicate instance of ${this.name}`, - })); - - clone.add(function* () { - const i = new LocalVariable('clone', dotnet.Var, { - initializer: $this.new() - }); - yield i.declarationStatement; - - if ($this.state.project.azure) { - for (const f of [$this.correlationId, $this.processRecordId, $this.defaultProfile]) { - yield `${i.value}.${f} = this.${f};`; - } - } - for (const f of [$this.invocationInfo, 'Proxy', 'Pipeline', 'AsJob', 'Break', 'ProxyCredential', 'ProxyUseDefaultCredentials', 'HttpPipelinePrepend', 'HttpPipelineAppend',]) { - yield `${i.value}.${f} = this.${f};`; - } - - for (const f of $this.thingsToSerialize) { - yield `${i.value}.${f} = this.${f};`; - } - - // _name = this._name, - //_parametersBody = this._parametersBody, - //_resourceGroupName = this._resourceGroupName, - //_subscriptionId = this._subscriptionId, - - yield Return(i); - }); - } - } - - private implementConstructors() { - // default constructor - this.add(new Constructor(this, { description: `Intializes a new instance of the cmdlet class.` })); - } - - private implementIEventListener() { - const $this = this; - const cts = this.add(new Field('_cancellationTokenSource', System.Threading.CancellationTokenSource, { - access: Access.Private, - initialValue: new LiteralExpression(`new ${System.Threading.CancellationTokenSource.declaration}()`), - description: `The for this operation.` - })); - this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Token`, System.Threading.CancellationToken, new LiteralExpression(`${cts.value}.Token`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation token.' })); - this.cancellationToken = toExpression(`((${ClientRuntime.IEventListener})this).Token`); - this.add(new LambdaProperty(`${ClientRuntime.IEventListener}.Cancel`, System.Action(), new LiteralExpression(`${cts.value}.Cancel`), { getAccess: Access.Default, setAccess: Access.Default, description: ' cancellation delegate. Stops the cmdlet when called.' })); - - const id = new Parameter('id', dotnet.String, { description: 'The message id' }); - const token = new Parameter('token', System.Threading.CancellationToken, { description: 'The message cancellation token. When this call is cancelled, this should be true' }); - const messageData = new Parameter('messageData', System.Func(ClientRuntime.EventData), { description: 'Detailed message data for the message event.' }); - const signalMethod = this.add(new Method(`${ClientRuntime.IEventListener}.Signal`, System.Threading.Tasks.Task(), { - async: Modifier.Async, - parameters: [id, token, messageData], - access: Access.Default, - description: 'Handles/Dispatches events during the call to the REST service.', - returnsDescription: `A that will be complete when handling of the message is completed.` - })); - signalMethod.push(Using('NoSynchronizationContext', '')); - - signalMethod.add(function* () { - yield If(`${token.value}.IsCancellationRequested`, Return()); - - // if the - - const sw = Switch(id, [ - TerminalCase(Events.Verbose.value, function* () { - yield `WriteVerbose($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - - TerminalCase(Events.Warning.value, function* () { - yield `WriteWarning($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - TerminalCase(Events.Information.value, function* () { - if ($this.operation.asjob) { - yield '// When an operation supports asjob, Information messages must go thru verbose.'; - yield `WriteVerbose($"INFORMATION: {(messageData().Message ?? ${System.String.Empty})}");`; - } - else { - const data = new LocalVariable('data', dotnet.Var, { initializer: new LiteralExpression(`${messageData.use}()`) }); - yield data.declarationStatement; - yield 'WriteInformation(data, new[] { data.Message });'; - } - yield Return(); - - }), - TerminalCase(Events.Debug.value, function* () { - yield `WriteDebug($"{(messageData().Message ?? ${System.String.Empty})}");`; - yield Return(); - }), - TerminalCase(Events.Error.value, function* () { - yield 'WriteError(new global::System.Management.Automation.ErrorRecord( new global::System.Exception(messageData().Message), string.Empty, global::System.Management.Automation.ErrorCategory.NotSpecified, null ) );'; - yield Return(); - }), - ]); - - if ($this.operation.asjob) { - // if we support -AsJob, we support -NoWait - sw.add(Case(Events.DelayBeforePolling.value, function* () { - yield If('true == MyInvocation?.BoundParameters?.ContainsKey("NoWait")', function* () { - yield 'var data = messageData();'; - yield 'if (data.ResponseMessage is System.Net.Http.HttpResponseMessage response)'; - yield '{'; - yield ' var asyncOperation = response.GetFirstHeader(@"Azure-AsyncOperation");'; - yield ' var location = response.GetFirstHeader(@"Location");'; - yield ' var uri = global::System.String.IsNullOrEmpty(asyncOperation) ? global::System.String.IsNullOrEmpty(location) ? response.RequestMessage.RequestUri.AbsoluteUri : location : asyncOperation;'; - yield ` WriteObject(new ${ClientRuntime}.PowerShell.AsyncOperationResponse { Target = uri });`; - - yield ' // do nothing more. '; - yield ' data.Cancel();'; - yield ' return;'; - yield '}'; - }); - })); - } - - // the whole switch statement - yield sw; - - if ($this.state.project.azure) { - // in azure mode, we signal the AzAccount module with every event that makes it here. - yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`; - yield If(`${token.value}.IsCancellationRequested`, Return()); - } else { - // In Non-Azure Modes, emit the Signal method without coorelation and processrecordid - yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`; - yield If(`${token.value}.IsCancellationRequested`, Return()); - } - yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`; - // any handling of the signal on our side... - }); - } - - private addPowershellParameters(operation: command.CommandOperation) { - const vps = operation.details.csharp.virtualParameters || { - body: [], - operation: [], - }; - - for (const parameter of values(operation.parameters)) { - // these are the parameters that this command expects - const td = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema, true, this.state); - - if (parameter.details.csharp.constantValue) { - // this parameter has a constant value -- SKIP IT - continue; - } - - if (parameter.details.csharp.fromHost) { - // the parameter is expected to be gotten from the host.(ie, Az.Accounts) - - const hostParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { - metadata: { - parameterDefinition: parameter.details.csharp.httpParameter - }, - description: parameter.details.csharp.description, - })); - this.thingsToSerialize.push(hostParameter); - // in the BeginProcessing, we should tell it to go get the value for this property from the common module - this.$('BeginProcessing').add(hostParameter.assignPrivate(new LiteralExpression(`${this.state.project.serviceNamespace.moduleClass.declaration}.Instance.GetParameter(this.MyInvocation, ${this.correlationId.value}, "${parameter.name}") as string`))); - continue; - } - const $this = this; - - if (parameter.details.csharp.apiversion) { - // Api-version parameters for azure are a custom implementation - this.add(new Property(parameter.details.csharp.name, td, { - getAccess: Access.Internal, - setAccess: Access.Private, - metadata: { - parameterDefinition: parameter.details.csharp.httpParameter - }, - description: parameter.details.csharp.description, - *get() { - const metadata = operation.extensions['x-ms-metadata']; - const profiles = >metadata.profiles || new Dictionary(); - - yield Switch(`${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Profile`, function* () { - for (const { key: profileName, value: apiVersion } of items(profiles)) { - yield TerminalCase(`"${profileName}"`, Return(`"${apiVersion}"`)); - } - yield TerminalDefaultCase(Return(`"${metadata.apiVersions[0]}"`)); - }); - } - })); - continue; - } - - if (this.dropBodyParameter && parameter.details.csharp.isBodyParameter) { - // we're supposed to use parameters for the body parameter instead of a big object - const expandedBodyParameter = this.add(new BackedProperty(parameter.details.csharp.name, td, { - description: parameter.details.csharp.description, - - initializer: (parameter.schema.type === JsonType.Array) ? 'null' : `new ${parameter.schema.details.csharp.fullname}()`, - setAccess: Access.Private, - getAccess: Access.Private, - })); - this.thingsToSerialize.push(expandedBodyParameter); - - for (const vParam of vps.body) { - const vSchema = vParam.schema; - const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); - - // we need to know if the actual underlying property is actually nullable. - const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, (vParam.origin).property.details.csharp.required, this.state).isNullable; - - const cmdletParameter = new Property(vParam.name, propertyType, { - get: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ - // get: toExpression(`null == ${expandedBodyParameter.value}.${vParam.origin.name} ? ${propertyType.defaultOfType} : (${propertyType.declaration}) ${expandedBodyParameter.value}.${vParam.origin.name}`), - set: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), - new: PropertiesRequiringNew.has(vParam.name) ? Modifier.New : Modifier.None - }); - - if (vParam.schema.details.csharp.byReference) { - // this parameter's schema is marked as 'by-reference' which means we should - // tag it with an ExportAs attribute for the I*Reference type. - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.details.csharp.referenceInterface})`] })); - } - - if (vParam.schema.type === JsonType.Array) { - if (vParam.schema.items && vParam.schema.items.details.csharp.byReference) { - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${vParam.schema.items.details.csharp.referenceInterface}[])`] })); - } - cmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); - } - - if (vSchema.additionalProperties) { - // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // if it's a standalone dictionary, we can just use hashtable instead - if (length(vSchema.properties) === 0) { - // it's a pure dictionary - // add an attribute for changing the exported type. - cmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - } else { - // it's a hybrid. We need to add an additional property that puts its items into the target container - - } - - } - - const desc = (vParam.description || '.').replace(/[\r?\n]/gm, ''); - cmdletParameter.description = desc; - - // check if this parameter is a byte array, which would indicate that it should really be a file input - if (cmdletParameter.type.declaration === dotnet.Binary.declaration) { - // set the generated parameter to internal - cmdletParameter.setAccess = Access.Internal; - cmdletParameter.getAccess = Access.Internal; - - // create a InputFileXXX for the parameter - const ifname = vParam.name.toLowerCase() === 'value' ? 'InputFile' : pascalCase([vParam.name, 'Input', 'File']); - - const inputFileParameter = new Property(ifname, dotnet.String, { - // get: toExpression(`${expandedBodyParameter.value}.${vParam.origin.name}${vParam.required ? '' : ` ?? ${propertyType.defaultOfType}`}`), - set: function* () { - const provider = Local('provider'); - provider.initializer = undefined; - const paths = Local('paths', `this.SessionState.Path.GetResolvedProviderPathFromPSPath(value, out ${provider.declarationExpression})`); - yield paths.declarationStatement; - yield If(`${provider.value}.Name != "FileSystem" || ${paths.value}.Count == 0`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Invalid input path."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); - yield If(`${paths.value}.Count > 1`, 'ThrowTerminatingError( new System.Management.Automation.ErrorRecord(new global::System.Exception("Multiple input paths not allowed."),string.Empty, global::System.Management.Automation.ErrorCategory.InvalidArgument, value) );'); - yield cmdletParameter.assign(`global::System.IO.File.ReadAllBytes(${paths.value}[0])`); - }, - description: `Input File for ${cmdletParameter.name} (${escapeString(desc)})` - }); - - inputFileParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "Input File for ${cmdletParameter.name} (${escapeString(desc || '.')})"`)] })); - inputFileParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - - $this.add(inputFileParameter); - } else { - cmdletParameter.add(new Attribute(ParameterAttribute, { parameters: [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(desc || '.')}"`)] })); - cmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Body`] })); - addInfoAttribute(cmdletParameter, propertyType, !!vParam.required, false, desc, (vParam.origin).property.serializedName); - addCompleterInfo(cmdletParameter, vParam); - addDefaultInfo(cmdletParameter, vParam); - } - - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; - if (isEnum || hasEnum) { - cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); - } - // add aliases if there is any - if (length(vParam.alias) > 0) { - cmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); - } - - this.add(cmdletParameter); - } - - if (parameter.schema.additionalProperties) { - // if there is an additional properties on this type - // add a hashtable parameter for additionalProperties - let apPropName = ''; - const options = ['AdditionalProperties', 'MoreProperties', 'ExtendedProperties', 'Properties']; - for (const n of options) { - if (this.properties.find(each => each.name === n)) { - continue; - } - apPropName = n; - break; - } - - this.apProp = this.add(new Property(apPropName, System.Collections.Hashtable)); - this.apProp.add(new Attribute(ParameterAttribute, { - parameters: ['Mandatory = false', 'HelpMessage = "Additional Parameters"'] - })); - this.bodyParameterInfo = { - type: { - declaration: parameter.schema.details.csharp.fullname - }, - valueType: parameter.schema.additionalProperties === true ? System.Object : this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(parameter.schema.additionalProperties, true, this.state) - }; - } - - this.bodyParameter = expandedBodyParameter; - continue; - } - } - - if (this.isViaIdentity) { - // add in the pipeline parameter for the identity - - const idschema = values(this.state.project.model.schemas).first(each => each.details.default.uid === 'universal-parameter-type'); - const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state); - const idParam = this.add(new BackedProperty('InputObject', idtd, { - description: 'Identity Parameter' - })); - const parameters = [new LiteralExpression('Mandatory = true'), new LiteralExpression('HelpMessage = "Identity Parameter"'), new LiteralExpression('ValueFromPipeline = true')]; - idParam.add(new Attribute(ParameterAttribute, { parameters })); - idParam.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Path`] })); - } - for (const vParam of values(vps.operation)) { - const vSchema = vParam.schema; - const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state); - - - const origin = vParam.origin; - - const regularCmdletParameter = (this.state.project.azure && vParam.name === 'SubscriptionId' && operation.details.csharp.verb.toLowerCase() === 'get') ? - - // special case for subscription id - this.add(new BackedProperty(vParam.name, dotnet.StringArray, { - metadata: { - parameterDefinition: origin.details.csharp.httpParameter - }, - description: vParam.description - })) : - - // everything else - this.add(new BackedProperty(vParam.name, propertyType, { - metadata: { - parameterDefinition: origin.details.csharp.httpParameter - }, - description: vParam.description - })); - - if (vSchema.additionalProperties) { - // we have to figure out if this is a standalone dictionary or a hybrid object/dictionary. - // if it's a hybrid, we have to create another parameter like -AdditionalProperties and have that dump the contents into the dictionary - // if it's a standalone dictionary, we can just use hashtable instead - if (length(vSchema.properties) === 0) { - // it's a pure dictionary - // change the property type to hashtable. - // add an attribute to change the exported type. - regularCmdletParameter.add(new Attribute(ExportAsAttribute, { parameters: [`typeof(${System.Collections.Hashtable})`] })); - } else { - // it's a hybrid. We need to add an additional property that puts its items into the target container - - } - - } - - this.thingsToSerialize.push(regularCmdletParameter); - - const parameters = [new LiteralExpression(`Mandatory = ${vParam.required ? 'true' : 'false'}`), new LiteralExpression(`HelpMessage = "${escapeString(vParam.description) || '.'}"`)]; - if (origin.details.csharp.isBodyParameter) { - parameters.push(new LiteralExpression('ValueFromPipeline = true')); - this.bodyParameter = regularCmdletParameter; - } - regularCmdletParameter.add(new Attribute(ParameterAttribute, { parameters })); - if (vParam.schema.type === JsonType.Array) { - regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute)); - } - - addInfoAttribute(regularCmdletParameter, propertyType, vParam.required, false, vParam.description, vParam.origin.name); - addCompleterInfo(regularCmdletParameter, vParam); - addDefaultInfo(regularCmdletParameter, vParam); - - // add aliases if there is any - if (length(vParam.alias) > 0) { - regularCmdletParameter.add(new Attribute(Alias, { parameters: vParam.alias.map(x => '"' + x + '"') })); - } - - const httpParam = origin.details.csharp.httpParameter; - const uid = httpParam ? httpParam.details.csharp.uid : 'no-parameter'; - - const cat = values(operation.callGraph[0].parameters). - where(each => !(each.details.csharp.constantValue)). - first(each => each.details.csharp.uid === uid); - - if (cat) { - regularCmdletParameter.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.${pascalCase(cat.in)}`] })); - } - - - if (origin.details.csharp.completer) { - // add the completer to this class and tag this parameter with the completer. - // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); - } - - const isEnum = !(propertyType.schema instanceof NewSchema) && propertyType.schema.details.csharp.enum !== undefined; - const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; - if (isEnum || hasEnum) { - regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); - } - } - const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); - if (ifmatch) { - //no sure why there is an empty block - } - - } - - private addClassAttributes(operation: command.CommandOperation, variantName: string) { - const cmdletAttribParams: Array = [ - category[operation.details.csharp.verb] ? verbEnum(category[operation.details.csharp.verb], operation.details.csharp.verb) : `"${operation.details.csharp.verb}"`, - new StringExpression(variantName) - ]; - - if (this.isWritableCmdlet(operation)) { - cmdletAttribParams.push('SupportsShouldProcess = true'); - } - - if (operation.details.csharp.hidden) { - this.add(new Attribute(InternalExportAttribute)); - const noun = `${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; - const cmdletName = `${operation.details.csharp.verb}-${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; - this.state.message({ Channel: Channel.Debug, Text: `[DIRECTIVE] Applied 'hidden' directive to ${cmdletName}. Added attribute ${InternalExportAttribute.declaration} to cmdlet.` }); - } - - this.add(new Attribute(CmdletAttribute, { parameters: cmdletAttribParams })); - - // add alias attribute if there is any aliases for this cmdlet - if (length(operation.details.csharp.alias) > 0) { - this.add(new Attribute(Alias, { parameters: operation.details.csharp.alias.map((x: string) => '"' + x + '"') })); - } - - let shouldAddPassThru = false; - // set to hold the output types - const outputTypes = new Set(); - for (const httpOperation of values(operation.callGraph)) { - const pageableInfo = httpOperation.details.csharp.pageable; - for (const item of items(httpOperation.responses).where(each => each.key !== 'default')) { - for (const schema of values(item.value).selectNonNullable(each => each.schema)) { - const props = getAllProperties(schema); - - // does the target type just wrap a single output? - const resultSchema = length(props) !== 1 ? schema : props[0].schema; - - // make sure return type for boolean stays boolean! - if (resultSchema.type === JsonType.Boolean) { - outputTypes.add(`typeof(${dotnet.Bool})`); - } else { - const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state); - - if (typeDeclaration.declaration === System.IO.Stream.declaration || typeDeclaration.declaration === dotnet.Binary.declaration) { - // if this is a stream, skip the output type. - this.hasStreamOutput = true; - shouldAddPassThru = true; - outputTypes.add(`typeof(${dotnet.Bool})`); - } else { - - let type = ''; - if (typeDeclaration instanceof ArrayOf) { - type = typeDeclaration.elementTypeDeclaration; - } else if (!(typeDeclaration.schema instanceof NewSchema) && pageableInfo && pageableInfo.responseType === 'pageable') { - if (typeDeclaration === undefined || typeDeclaration.schema.properties[pageableInfo.itemName] === undefined) { - throw new Error(`\n\nOn operation:\n '${httpOperation.operationId}' at '${httpOperation.path}'\n -- you have used 'x-ms-pageable' and there is no property name '${pageableInfo.itemName}' that is an array.\n\n`); - } - const nestedSchema = typeDeclaration.schema.properties[pageableInfo.itemName].schema; - const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); - type = (nestedTypeDeclaration).elementTypeDeclaration; - } else { - type = typeDeclaration.declaration; - } - // check if this is a stream output - if (type) { - outputTypes.add(`typeof(${type})`); - } - } - } - } - } - } - - // if any response does not return, - // the cmdlet should have a PassThru parameter - shouldAddPassThru = shouldAddPassThru || values(operation.callGraph) - .selectMany(httpOperation => items(httpOperation.responses)) - .selectMany(responsesItem => responsesItem.value) - .any(value => value.schema === undefined); - if (outputTypes.size === 0) { - outputTypes.add(`typeof(${dotnet.Bool})`); - } - - this.add(new Attribute(OutputTypeAttribute, { parameters: [...outputTypes] })); - if (shouldAddPassThru) { - const passThru = this.add(new Property('PassThru', SwitchParameter, { description: 'When specified, forces the cmdlet return a \'bool\' given that there isn\'t a return type by default.' })); - passThru.add(new Attribute(ParameterAttribute, { parameters: ['Mandatory = false', 'HelpMessage = "Returns true when the command succeeds"'] })); - passThru.add(new Attribute(CategoryAttribute, { parameters: [`${ParameterCategory}.Runtime`] })); - } - - this.add(new Attribute(DescriptionAttribute, { parameters: [new StringExpression(this.description)] })); - this.add(new Attribute(GeneratedAttribute)); - if (operation.extensions && operation.extensions['x-ms-metadata'] && operation.extensions['x-ms-metadata'].profiles) { - const profileNames = Object.keys(operation.extensions && operation.extensions['x-ms-metadata'].profiles); - // wrap profile names - profileNames.forEach((element, index) => { - profileNames[index] = `"${element}"`; - }); - - this.add(new Attribute(ProfileAttribute, { parameters: [...profileNames] })); - } - } -} - export class NewCmdletClass extends Class { private cancellationToken!: Expression; public state: NewState; @@ -1517,7 +307,7 @@ export class NewCmdletClass extends Class { private hasStreamOutput: boolean; private outFileParameter?: Property; - constructor(namespace: Namespace, operation: CommandOperation, state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, operation: CommandOperation, state: NewState, objectInitializer?: DeepPartial) { // generate the 'variant' part of the name const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; @@ -2401,9 +1191,9 @@ export class NewCmdletClass extends Class { const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, (vParam.origin).property.language.csharp?.required, this.state).isNullable; const cmdletParameter = new Property(vParam.name, propertyType, { - get: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ + get: toExpression(`${expandedBodyParameter.value}.${NewGetVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ // get: toExpression(`null == ${expandedBodyParameter.value}.${vParam.origin.name} ? ${propertyType.defaultOfType} : (${propertyType.declaration}) ${expandedBodyParameter.value}.${vParam.origin.name}`), - set: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), + set: toExpression(`${expandedBodyParameter.value}.${NewGetVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), new: PropertiesRequiringNew.has(vParam.name) ? Modifier.New : Modifier.None }); diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index 0be4317773..41046f3726 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -5,36 +5,10 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; -import { CmdletClass, NewCmdletClass } from './class'; +import { NewState } from '../internal/state'; +import { NewCmdletClass } from './class'; import { DeepPartial } from '@azure-tools/codegen'; -export class CmdletNamespace extends Namespace { - inputModels = new Array(); - public get outputFolder(): string { - return this.state.project.cmdletFolder; - } - - constructor(parent: Namespace, private state: State, objectInitializer?: DeepPartial) { - super('Cmdlets', parent); - this.apply(objectInitializer); - } - - async init() { - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // generate cmdlet classes on top of the SDK - for (const { key: index, value: operation } of items(this.state.model.commands.operations)) { - // skip ViaIdentity for set-* cmdlets. - if (this.state.project.azure && operation.details.csharp.verb === 'Set' && operation.details.csharp.name.indexOf('ViaIdentity') > 0) { - continue; - } - this.addClass(await new CmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); - } - return this; - } -} - export class NewCmdletNamespace extends Namespace { inputModels = new Array(); public get outputFolder(): string { diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index 63d3ff4167..bc958d1729 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -5,128 +5,19 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { EnumDetails } from '@azure-tools/codemodel-v3'; import { If, Parameter, Method, Namespace, System, Struct, Attribute, Class, dotnet, LambdaMethod, LiteralExpression, Modifier } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../internal/state'; +import { NewState } from '../internal/state'; import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, TypeConverterAttribute, PSTypeConverter } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; import { EnumDetails as NewEnumDetails } from '../utils/schema'; -export class EnumNamespace extends Namespace { - public get outputFolder(): string { - return join(this.state.project.apiFolder, 'Support'); - } - - constructor(parent: Namespace, public state: State, objectInitializer?: DeepPartial) { - super('Support', parent); - this.apply(objectInitializer); - - const enumInfos = values(state.model.schemas) - .where(each => each.details.csharp.enum !== undefined && !each.details.csharp.skip) - .select(each => ({ details: each.details.csharp.enum, description: each.details.csharp.description })) - .toArray(); - - const done = new Set(); - - - for (const enumInfo of enumInfos) { - if (done.has(enumInfo.details.name)) { - continue; - } - - done.add(enumInfo.details.name); - - if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) { - continue; - } - - // generate a typeconverter for the enum class too. - - const enumValues = values(enumInfo.details.values).select(v => v.value).toArray(); - const enumClass = new Struct(this, enumInfo.details.name, undefined, { - interfaces: [IArgumentCompleter], - partial: true, - description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`, - fileName: `${enumInfo.details.name}.Completer` - }); - const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' }); - const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' }); - const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' }); - const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' }); - const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' }); - const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters]; - - enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () { - for (const enumValue of enumValues) { - yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`, - `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`); - } - }); - - - // generate a typeconverter for the enum class too. - - const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, { - interfaces: [PSTypeConverter], - partial: true, - description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`, - fileName: `${enumInfo.details.name}.TypeConverter` - }); - - converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - - converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - - converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })); - - converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], description: 'NotImplemented -- this will return null', - returnsDescription: 'will always return null.' - })); - - enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - - } - } -} export class NewEnumNamespace extends Namespace { public get outputFolder(): string { return join(this.state.project.apiFolder, 'Support'); } - constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); //const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] diff --git a/powershell/generators/csproj.ts b/powershell/generators/csproj.ts index 0d14a60d7d..84d3b71bc4 100644 --- a/powershell/generators/csproj.ts +++ b/powershell/generators/csproj.ts @@ -3,13 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project } from '../internal/project'; import { NewProject } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateCsproj(project: Project | NewProject) { +export async function generateCsproj(project: NewProject) { const release = project.azure ? ` true true MSSharedLibKey.snk diff --git a/powershell/generators/gitattributes.ts b/powershell/generators/gitattributes.ts index 764cdd68dd..165e310abe 100644 --- a/powershell/generators/gitattributes.ts +++ b/powershell/generators/gitattributes.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; -export async function generateGitAttributes(project: Project | NewProject) { +export async function generateGitAttributes(project: NewProject) { project.state.writeFile(project.gitAttributes, '* text=auto', undefined, 'source-file-other'); } \ No newline at end of file diff --git a/powershell/generators/gitignore.ts b/powershell/generators/gitignore.ts index 84764c3f37..ef4d362f0c 100644 --- a/powershell/generators/gitignore.ts +++ b/powershell/generators/gitignore.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; -export async function generateGitIgnore(project: Project | NewProject) { +export async function generateGitIgnore(project: NewProject) { project.state.writeFile(project.gitIgnore, `bin obj .vs diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index ac810323da..d60fce6a8d 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateNuspec(project: Project | NewProject) { +export async function generateNuspec(project: NewProject) { const dependencies = project.azure ? ` diff --git a/powershell/generators/psm1.custom.ts b/powershell/generators/psm1.custom.ts index 61789f414c..f493b41c00 100644 --- a/powershell/generators/psm1.custom.ts +++ b/powershell/generators/psm1.custom.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; -export async function generatePsm1Custom(project: Project | NewProject) { +export async function generatePsm1Custom(project: NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Custom) || ''); const dllPath = relative(project.customFolder, project.dll); const internalPath = relative(project.customFolder, project.psm1Internal); diff --git a/powershell/generators/psm1.internal.ts b/powershell/generators/psm1.internal.ts index d1e0a2e612..6ce88de483 100644 --- a/powershell/generators/psm1.internal.ts +++ b/powershell/generators/psm1.internal.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; import { getProfileExportScript } from './psm1'; -export async function generatePsm1Internal(project: Project | NewProject) { +export async function generatePsm1Internal(project: NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Internal) || ''); const dllPath = relative(project.internalFolder, project.dll); psm1.prepend('Generated', ` diff --git a/powershell/generators/psm1.ts b/powershell/generators/psm1.ts index 78f1c22af6..f63e1f4eea 100644 --- a/powershell/generators/psm1.ts +++ b/powershell/generators/psm1.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; @@ -40,7 +40,7 @@ export function getProfileExportScript(exportFolderScript: string, isAzure: bool `; } -export async function generatePsm1(project: Project | NewProject) { +export async function generatePsm1(project: NewProject) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1) || ''); let azureInitialize = ''; if (project.azure) { diff --git a/powershell/generators/readme.ts b/powershell/generators/readme.ts index 384d87b168..79a5f2d87c 100644 --- a/powershell/generators/readme.ts +++ b/powershell/generators/readme.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; import { MdFile } from '../file-formats/md-file'; -export async function generateReadme(project: Project | NewProject) { +export async function generateReadme(project: NewProject) { const md = new MdFile(await project.state.readFile(project.readme) || ''); let azureInfo = ''; if (project.azure) { diff --git a/powershell/generators/script-cmdlet.ts b/powershell/generators/script-cmdlet.ts index ac1c25ee24..b0839de113 100644 --- a/powershell/generators/script-cmdlet.ts +++ b/powershell/generators/script-cmdlet.ts @@ -4,10 +4,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Project, NewProject } from '../internal/project'; +import { NewProject } from '../internal/project'; import { serialize, indent, setIndentation, applyOverrides, pascalCase } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; -import { State } from '../internal/state'; import { dotnet, System } from '@azure-tools/codegen-csharp'; import { PSScriptFile } from '../file-formats/psscript-file'; @@ -52,7 +51,7 @@ function getType(type: string) { return type; } -export async function generateScriptCmdlets(project: Project | NewProject) { +export async function generateScriptCmdlets(project: NewProject) { const commands = await project.state.getValue>('command', []); for (const command of values(commands)) { if (!command.action) { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index 2b57a317d8..faf94d08c2 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,19 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDefinitionResolver, SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewBoolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; -import { State, NewState } from './state'; +import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewBoolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; +import { NewState } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { EnumNamespace, NewEnumNamespace } from '../enums/namespace'; -import { ModelExtensionsNamespace, NewModelExtensionsNamespace } from '../models/model-extensions'; +import { NewEnumNamespace } from '../enums/namespace'; +import { NewModelExtensionsNamespace } from '../models/model-extensions'; -import { ModuleNamespace, NewModuleNamespace } from '../module/module-namespace'; -import { CmdletNamespace, NewCmdletNamespace } from '../cmdlets/namespace'; +import { NewModuleNamespace } from '../module/module-namespace'; +import { NewCmdletNamespace } from '../cmdlets/namespace'; import { Host } from '@azure-tools/autorest-extension-base'; -import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType, } from '@azure-tools/codemodel-v3'; +import { codemodel, PropertyDetails, exportedModels as T } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { BooleanSchema, ChoiceSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; export type Schema = T.SchemaT, LanguageDetails>; @@ -40,24 +40,6 @@ export class PSSwitch extends Boolean { } -export class PSSchemaResolver extends SchemaDefinitionResolver { - inResolve = false; - resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { - const before = this.inResolve; - try { - if (!this.inResolve) { - this.inResolve = true; - if (schema && schema.type === JsonType.Boolean) { - return new PSSwitch(schema, required); - } - } - - return super.resolveTypeDeclaration(schema, required, state); - } finally { - this.inResolve = before; - } - } -} export class NewPSSwitch extends NewBoolean { get declaration(): string { @@ -67,7 +49,7 @@ export class NewPSSwitch extends NewBoolean { } export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { inResolve = false; - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): NewEnhancedTypeDeclaration { const before = this.inResolve; try { if (!this.inResolve) { @@ -86,165 +68,6 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { } } -export class Project extends codeDomProject { - public azure!: boolean; - public license!: string; - public cmdletFolder!: string; - - public customFolder!: string; - public utilsFolder!: string; - public internalFolder!: string; - public testFolder!: string; - public runtimeFolder!: string; - public binFolder!: string; - public objFolder!: string; - public exportsFolder!: string; - public docsFolder!: string; - public examplesFolder!: string; - public resourcesFolder!: string; - public serviceName!: string; - public moduleName!: string; - public csproj!: string; - public nuspec!: string; - public gitIgnore!: string; - public gitAttributes!: string; - public readme!: string; - public dllName!: string; - public dll!: string; - public psd1!: string; - public psm1!: string; - public psm1Custom!: string; - public psm1Internal!: string; - public formatPs1xml!: string; - public apiFolder!: string; - public baseFolder!: string; - public moduleFolder!: string; - public schemaDefinitionResolver!: SchemaDefinitionResolver; - public moduleVersion!: string; - public profiles!: Array; - - public prefix!: string; - public subjectPrefix!: string; - public projectNamespace!: string; - public overrides!: Dictionary; - public serviceNamespace!: ModuleNamespace; - public supportNamespace!: EnumNamespace; - public cmdlets!: CmdletNamespace; - - public modelsExtensions!: ModelExtensionsNamespace; - public accountsVersionMinimum!: string; - public dependencyModuleFolder!: string; - public metadata!: Metadata; - public state!: State; - public helpLinkPrefix!: string; - get model() { return this.state.model; } - - constructor(protected service: Host, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - - - public async init(): Promise { - await super.init(); - this.state = await new State(this.service).init(this); - - this.schemaDefinitionResolver = new PSSchemaResolver(); - - this.projectNamespace = this.state.model.details.csharp.namespace; - - - this.overrides = { - 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, - 'using Data;': '', - 'using Parser;': '', - 'using Converters;': '', - 'using Internal.Extensions;': '', - - 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, - 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, - 'Microsoft.Rest': `${this.projectNamespace}`, - }; - - // Values - this.moduleVersion = await this.state.getValue('module-version'); - this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || []; - this.accountsVersionMinimum = '1.8.1'; - this.helpLinkPrefix = await this.state.getValue('help-link-prefix'); - this.metadata = await this.state.getValue('metadata'); - this.license = await this.state.getValue('header-text', ''); - - // Flags - this.azure = this.model.details.default.isAzure; - - // Names - this.prefix = this.model.details.default.prefix; - this.serviceName = this.model.details.default.serviceName; - this.subjectPrefix = this.model.details.default.subjectPrefix; - this.moduleName = await this.state.getValue('module-name'); - this.dllName = await this.state.getValue('dll-name'); - - // Folders - this.baseFolder = await this.state.getValue('current-folder'); - this.moduleFolder = await this.state.getValue('module-folder'); - this.cmdletFolder = await this.state.getValue('cmdlet-folder'); - - this.customFolder = await this.state.getValue('custom-cmdlet-folder'); - this.utilsFolder = await this.state.getValue('utils-cmdlet-folder'); - this.internalFolder = await this.state.getValue('internal-cmdlet-folder'); - this.testFolder = await this.state.getValue('test-folder'); - this.runtimeFolder = await this.state.getValue('runtime-folder'); - this.apiFolder = await this.state.getValue('api-folder'); - - this.binFolder = await this.state.getValue('bin-folder'); - this.objFolder = await this.state.getValue('obj-folder'); - this.exportsFolder = await this.state.getValue('exports-folder'); - this.docsFolder = await this.state.getValue('docs-folder'); - this.dependencyModuleFolder = await this.state.getValue('dependency-module-folder'); - this.examplesFolder = await this.state.getValue('examples-folder'); - this.resourcesFolder = await this.state.getValue('resources-folder'); - - // File paths - this.csproj = await this.state.getValue('csproj'); - this.dll = await this.state.getValue('dll'); - this.psd1 = await this.state.getValue('psd1'); - this.psm1 = await this.state.getValue('psm1'); - this.psm1Custom = await this.state.getValue('psm1-custom'); - this.psm1Internal = await this.state.getValue('psm1-internal'); - this.formatPs1xml = await this.state.getValue('format-ps1xml'); - this.nuspec = await this.state.getValue('nuspec'); - this.gitIgnore = `${this.baseFolder}/.gitignore`; - this.gitAttributes = `${this.baseFolder}/.gitattributes`; - this.readme = `${this.baseFolder}/readme.md`; - - // add project namespace - this.serviceNamespace = new ModuleNamespace(this.state); - this.serviceNamespace.header = this.license; - this.addNamespace(this.serviceNamespace); - - this.supportNamespace = new EnumNamespace(this.serviceNamespace, this.state); - this.supportNamespace.header = this.license; - this.addNamespace(this.supportNamespace); - - this.modelsExtensions = new ModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); - this.modelsExtensions.header = this.license; - this.addNamespace(this.modelsExtensions); - - // add cmdlet namespace - this.cmdlets = await new CmdletNamespace(this.serviceNamespace, this.state).init(); - this.cmdlets.header = this.license; - this.addNamespace(this.cmdlets); - - - // abort now if we have any errors. - this.state.checkpoint(); - return this; - } -} export class NewProject extends codeDomProject { public azure!: boolean; @@ -299,7 +122,7 @@ export class NewProject extends codeDomProject { public helpLinkPrefix!: string; get model() { return this.state.model; } - constructor(protected service: Host, objectInitializer?: DeepPartial) { + constructor(protected service: Host, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } diff --git a/powershell/internal/state.ts b/powershell/internal/state.ts index 197c344362..7366941c83 100644 --- a/powershell/internal/state.ts +++ b/powershell/internal/state.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { codemodel, ModelState } from '@azure-tools/codemodel-v3'; +import { codemodel } from '@azure-tools/codemodel-v3'; import { Host, JsonPath, Session } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from './project'; +import { NewProject } from './project'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; export interface GeneratorSettings { @@ -24,33 +24,10 @@ export interface GeneratorSettings { apiFolder: string; } -export class State extends ModelState { - project!: Project; - - public constructor(service: Host, objectInitializer?: DeepPartial) { - super(service); - this.apply(objectInitializer); - } - - async init(project?: Project) { - if (project) { - this.project = project; - } - return await super.init(project); - } - - path(...childPath: JsonPath) { - // const result = new State(this.service, this); - // result.currentPath = [...this.currentPath, ...childPath]; - // return result; - return this; - } -} - -export class NewState extends NewModelState { +export class NewState extends ModelState { project!: NewProject; - public constructor(service: Host, objectInitializer?: DeepPartial) { + public constructor(service: Host, objectInitializer?: DeepPartial) { super(service); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/code-model.ts b/powershell/llcsharp/code-model.ts index e5e14bc05a..8dc2d75cac 100644 --- a/powershell/llcsharp/code-model.ts +++ b/powershell/llcsharp/code-model.ts @@ -4,17 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { codemodel, command, components, exportedModels as T, http, schema } from '@azure-tools/codemodel-v3'; -import { ModelInterface } from './model/interface'; -import { ModelClass } from './model/model-class'; +import { NewModelInterface } from './model/interface'; +import { NewModelClass } from './model/model-class'; import { EnhancedTypeDeclaration } from './schema/extended-type-declaration'; // C# specific details for components export interface SchemaDetails extends schema.SchemaDetails { typeDeclaration?: EnhancedTypeDeclaration; - classImplementation?: ModelClass; - interfaceImplementation?: ModelInterface; - internalInterfaceImplementation?: ModelInterface; + classImplementation?: NewModelClass; + interfaceImplementation?: NewModelInterface; + internalInterfaceImplementation?: NewModelInterface; interfaceName?: string; internalInterfaceName?: string; fullInternalInterfaceName?: string; diff --git a/powershell/llcsharp/enums/enum.ts b/powershell/llcsharp/enums/enum.ts index 8f4303e708..aca6b1476e 100644 --- a/powershell/llcsharp/enums/enum.ts +++ b/powershell/llcsharp/enums/enum.ts @@ -22,174 +22,11 @@ import { Struct } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -export class EnumClass extends Struct implements EnhancedTypeDeclaration { - implementation: EnumImplementation; - get schema(): Schema { - return this.implementation.schema; - } - get convertObjectMethod() { - return this.implementation.convertObjectMethod; - } - - get defaultOfType() { - return toExpression('null /* enum value */'); - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.implementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.implementation.deserializeFromNode(mediaType, node, defaultValue); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.implementation.deserializeFromString(mediaType, content, defaultValue); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.implementation.deserializeFromResponse(mediaType, content, defaultValue); - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.implementation.serializeToNode(mediaType, value, serializedName, mode); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.implementation.serializeToContent(mediaType, value, mode); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.implementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.implementation.isXmlAttribute; - } - - get isNullable(): boolean { - return this.implementation.isNullable; - } - - get isRequired(): boolean { - return this.implementation.isRequired; - } - - constructor(schemaWithFeatures: EnumImplementation, state: State, objectInitializer?: DeepPartial) { - if (!schemaWithFeatures.schema.details.csharp.enum) { - throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.details.csharp.name}`); - } - - super(state.project.supportNamespace, schemaWithFeatures.schema.details.csharp.enum.name, undefined, { - interfaces: [new Interface(new Namespace('System'), 'IEquatable', { - genericParameters: [`${schemaWithFeatures.schema.details.csharp.enum.name}`] - })], - }); - this.description = schemaWithFeatures.schema.details.csharp.description; - this.implementation = schemaWithFeatures; - this.partial = true; - - this.apply(objectInitializer); - - // add known enum values - for (const evalue of schemaWithFeatures.schema.details.csharp.enum.values) { - this.addField(new Field(evalue.name, this, { initialValue: new StringExpression(evalue.value), static: Modifier.Static, description: evalue.description })); - } - - // add backingField - const backingField = this.add(new Property('_value', dotnet.String, { - getAccess: Access.Private, - setAccess: Access.Private, - description: `the value for an instance of the Enum.` - })); - - // add private constructor - const p = new Parameter('underlyingValue', dotnet.String, { description: 'the value to create an instance for.' }); - const ctor = this.addMethod(new Constructor(this, { - access: Access.Private, - parameters: [p], - description: `Creates an instance of the ` - })).add(`this.${backingField.value} = ${p.value};`); - - // add toString Method - this.addMethod(new Method('ToString', dotnet.String, { - override: Modifier.Override, - description: `Returns string representation for ${this.name}`, - returnsDescription: 'A string for this value.' - })).add(`return this.${backingField.value};`); - - // add Equals Method(thistype) - this.addMethod(new Method('Equals', dotnet.Bool, { - description: `Compares values of enum type ${this.name}`, - parameters: [new Parameter('e', this, { description: 'the value to compare against this instance.' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add(`return ${backingField.value}.Equals(e.${backingField.value});`); - - // add Equals Method(object) - this.addMethod(new Method('Equals', dotnet.Bool, { - override: Modifier.Override, - description: `Compares values of enum type ${this.name} (override for Object)`, - parameters: [new Parameter('obj', dotnet.Object, { description: 'the value to compare against this instance.' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add(`return obj is ${this.name} && Equals((${this.name})obj);`); - - // add implicit operator(string) - this.addMethod(new Operator(`implicit operator ${this.name}`, { - static: Modifier.Static, - description: `Implicit operator to convert string to ${this.name}`, - parameters: [new Parameter('value', dotnet.String, { description: `the value to convert to an instance of .` })] - })).add(`return new ${this.name}(value);`); - - // add static creation - this.addMethod(new Method('CreateFrom', dotnet.Object, { - static: Modifier.Static, - access: Access.Internal, - description: `Conversion from arbitrary object to ${this.name}`, - parameters: [new Parameter('value', dotnet.Object, { description: `the value to convert to an instance of .` })] - })).add(`return new ${this.name}(System.Convert.ToString(value));`); - - // add implicit operator(thistype) - this.addMethod(new Operator('implicit operator string', { - static: Modifier.Static, - description: `Implicit operator to convert ${this.name} to string`, - parameters: [new Parameter('e', this, { description: `the value to convert to an instance of .` })] - })).add(`return e.${backingField.value};`); - - // add operator == - this.addMethod(new Method('operator ==', dotnet.Bool, { - static: Modifier.Static, - description: `Overriding == operator for enum ${this.name}`, - parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], - returnsDescription: 'true if the two instances are equal to the same value' - })).add('return e2.Equals(e1);'); - - // add opeator != - this.addMethod(new Method('operator !=', dotnet.Bool, { - static: Modifier.Static, - description: `Overriding != operator for enum ${this.name}`, - parameters: [new Parameter('e1', this, { description: 'the value to compare against ' }), new Parameter('e2', this, { description: 'the value to compare against ' })], - returnsDescription: 'true if the two instances are not equal to the same value' - })).add('return !e2.Equals(e1);'); - - // add getHashCode - this.addMethod(new Method('GetHashCode', dotnet.Int, { - override: Modifier.Override, - description: `Returns hashCode for enum ${this.name}`, - returnsDescription: 'The hashCode of the value' - })).add(`return this.${backingField.value}.GetHashCode();`); - } - - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.implementation.validateValue(eventListener, property); - } - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.implementation.validatePresence(eventListener, property); - } -} - export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { implementation: NewEnumImplementation; get schema(): NewSchema { diff --git a/powershell/llcsharp/enums/json-serializer.ts b/powershell/llcsharp/enums/json-serializer.ts deleted file mode 100644 index 991df60b15..0000000000 --- a/powershell/llcsharp/enums/json-serializer.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Modifier } from '@azure-tools/codegen-csharp'; -import { Class } from '@azure-tools/codegen-csharp'; -import { Method } from '@azure-tools/codegen-csharp'; - -import { items } from '@azure-tools/linq'; -import { dotnet } from '@azure-tools/codegen-csharp'; -import { Namespace } from '@azure-tools/codegen-csharp'; -import { Parameter } from '@azure-tools/codegen-csharp'; -import { ClientRuntime } from '../clientruntime'; -import { State } from '../generator'; -import { DeepPartial } from '@azure-tools/codegen'; - -export class JsonSerializerClass extends Class { - - constructor(namespace: Namespace, protected state: State, objectInitializer?: DeepPartial) { - super(namespace, 'JsonSerialization'); - this.apply(objectInitializer); - - this.partial = true; - this.isStatic = true; - - const tojson = this.addMethod(new Method('ToJson', ClientRuntime.JsonNode, { static: Modifier.Static })); - const objP = tojson.addParameter(new Parameter('obj', dotnet.ThisObject)); - const container = tojson.addParameter(new Parameter('container', ClientRuntime.JsonObject, { defaultInitializer: dotnet.Null })); - tojson.add('return null;'); - - const schemas = state.model.schemas; - - // iterate thru all the models - // each model should have a class and an interface. - // if the class has a discriminator value, tell the parent model that it has children - for (const { key: index, value: schema } of items(schemas)) { - const state = this.state.path('components', 'schemas', index); - if (schema.details.csharp && schema.details.csharp.classImplementation) { - // must be a class. - // const implData: CSharpSchemaDetails = schema.details.csharp; - } - - schema.details; - const x = state.project.modelsNamespace.resolveTypeDeclaration(schema, true, state); - } - } -} diff --git a/powershell/llcsharp/enums/namespace.ts b/powershell/llcsharp/enums/namespace.ts index e8a9ec52d4..daf5c24d22 100644 --- a/powershell/llcsharp/enums/namespace.ts +++ b/powershell/llcsharp/enums/namespace.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Namespace } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class SupportNamespace extends Namespace { - constructor(parent: Namespace, private state: State | NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/generator.ts b/powershell/llcsharp/generator.ts index 644e9409f4..d7f6d57f95 100644 --- a/powershell/llcsharp/generator.ts +++ b/powershell/llcsharp/generator.ts @@ -3,44 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ModelState } from '@azure-tools/codemodel-v3'; import { codeModelSchema } from '@azure-tools/codemodel'; import { Model } from './code-model'; import { Host, JsonPath, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { Project, NewProject } from './project'; +import { NewProject } from './project'; import { Dictionary } from '@azure-tools/linq'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; -export class State extends ModelState { - project!: Project; - - public constructor(service: Host, objectInitializer?: DeepPartial) { - super(service); - this.apply(objectInitializer); - } - - async init(project?: Project) { - if (project) { - this.project = project; - } - return await super.init(project); - } - - path(...childPath: JsonPath) { - // const result = new State(this.service, this); - // result.currentPath = [...this.currentPath, ...childPath]; - //return result; - return this; - } -} - -export class NewState extends NewModelState { +export class NewState extends ModelState { project!: NewProject; - public constructor(service: Host, objectInitializer?: DeepPartial) { + public constructor(service: Host, objectInitializer?: DeepPartial) { super(service); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index dd7f399a09..c2db8c2512 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -9,9 +9,9 @@ import { Expression, ExpressionOrLiteral, Interface, Namespace, OneOrMoreStateme import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, Language, ObjectSchema } from '@azure-tools/codemodel'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ModelClass, NewModelClass } from './model-class'; +import { NewModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; @@ -124,157 +124,6 @@ export function newAddInfoAttribute(targetProperty: Property, pType: TypeDeclara } -export class ModelInterface extends Interface implements EnhancedTypeDeclaration { - get schema(): Schema { - return this.classImplementation.schema; - } - - get defaultOfType() { - return this.classImplementation.defaultOfType; - } - - get convertObjectMethod() { - return this.classImplementation.convertObjectMethod; - } - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.classImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.classImplementation.deserializeFromNode(mediaType, node, defaultValue); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.classImplementation.deserializeFromString(mediaType, content, defaultValue); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.classImplementation.deserializeFromResponse(mediaType, content, defaultValue); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.classImplementation.serializeToContent(mediaType, value, mode); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.classImplementation.serializeToNode(mediaType, value, serializedName, mode); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.classImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.classImplementation.isXmlAttribute; - } - - public isNullable = true; - - get isRequired(): boolean { - return this.classImplementation.isRequired; - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.classImplementation.validatePresence(eventListener, property); - } - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.classImplementation.validateValue(eventListener, property); - } - - get hasHeaderProperties(): boolean { - // disabled - // return this.classImplementation.hasHeaderProperties; - return false; - } - constructor(parent: TypeContainer, interfaceName: string, public classImplementation: ModelClass, public state: State, objectInitializer?: DeepPartial) { - super(parent, interfaceName); - this.partial = true; - this.apply(objectInitializer); - } - - get isInternal(): boolean { - return this.accessModifier === Access.Internal; - } - - init() { - (this).init = () => { }; // only allow a single init! - - const implData = (this.schema.details.csharp = this.schema.details.csharp || {}); - //implData.interfaceImplementation = this; - this.description = `${this.schema.details.csharp.description}`; - - const virtualProperties = this.schema.details.csharp.virtualProperties || { - owned: [], - inherited: [], - inlined: [] - }; - if (this.schema.details.csharp.virtualProperties) { - - for (const virtualProperty of values(virtualProperties.owned)) { - if (virtualProperty.private && !this.isInternal) { - continue; - } - - const modelProperty = virtualProperty.property; - - const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); - - const isRequired = !!modelProperty.details.csharp.required; - const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - description: modelProperty.details.csharp.description, - setAccess: internalSet ? Access.Internal : Access.Public - })); - - this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); - - if (!this.isInternal && modelProperty.details.csharp.constantValue !== undefined) { - p.setAccess = Access.Internal; - } - } - - for (const virtualProperty of values(virtualProperties.inlined)) { - - // don't publicly expose the 'private' properties. - if (virtualProperty.private && !this.isInternal) { - continue; - } - - const modelProperty = virtualProperty.property; - const isRequired = !!modelProperty.details.csharp.required; - const pType = this.state.project.modelsNamespace.resolveTypeDeclaration(modelProperty.schema, isRequired, this.state.path('schema')); - - const internalSet = !!(!this.isInternal && (modelProperty.details.csharp.readOnly || modelProperty.details.csharp.constantValue)); - - const p = this.add(new InterfaceProperty(virtualProperty.name, pType, { - description: modelProperty.details.csharp.description, - setAccess: internalSet ? Access.Internal : Access.Public - })); - this.addInfoAttribute(p, pType, isRequired, internalSet, modelProperty.details.csharp.description, modelProperty.serializedName); - - } - } - - if (!this.isInternal) { - // mark it as json serializable - if (!this.schema.details.csharp.isHeaderModel) { - if (this.state.project.jsonSerialization) { - this.interfaces.push(ClientRuntime.IJsonSerializable); - } - if (this.state.project.xmlSerialization) { - this.interfaces.push(ClientRuntime.IXmlSerializable); - } - } - } - return this; - } - - addInfoAttribute(p: Property, pType: TypeDeclaration, isRequired: boolean, internalSet: boolean, description: string, serializedName: string) { - if (!this.isInternal) { - return addInfoAttribute(p, pType, isRequired, internalSet, description, serializedName); - } - } -} export class NewModelInterface extends Interface implements NewEnhancedTypeDeclaration { get schema(): NewSchema { @@ -338,7 +187,7 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla // return this.classImplementation.hasHeaderProperties; return false; } - constructor(parent: TypeContainer, interfaceName: string, public classImplementation: NewModelClass, public state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: TypeContainer, interfaceName: string, public classImplementation: NewModelClass, public state: NewState, objectInitializer?: DeepPartial) { super(parent, interfaceName); this.partial = true; this.apply(objectInitializer); diff --git a/powershell/llcsharp/model/model-class-dictionary.ts b/powershell/llcsharp/model/model-class-dictionary.ts index 330cdd2f3e..bf86350a3d 100644 --- a/powershell/llcsharp/model/model-class-dictionary.ts +++ b/powershell/llcsharp/model/model-class-dictionary.ts @@ -3,119 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Field, System, Property, toExpression, dotnet, Parameter, ParameterModifier, Method, Class, TypeDeclaration, Indexer, Access, Variable, Expression, If, And, ForEach, LocalVariable, ImplicitCastOperator } from '@azure-tools/codegen-csharp'; -import { ModelClass, NewModelClass } from './model-class'; +import { NewModelClass } from './model-class'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; import { getAllVirtualProperties } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; import { DictionarySchema, ObjectSchema, SchemaType, Schema } from '@azure-tools/codemodel'; -export class DictionaryImplementation extends Class { - private get state() { return this.modelClass.state; } - private get schema() { return this.modelClass.schema; } - public valueType!: TypeDeclaration | EnhancedTypeDeclaration; - public ownsDictionary = false; - - constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - } - - init(valueType?: TypeDeclaration, accessViaMember?: Expression) { - if (valueType && accessViaMember) { - this.valueType = valueType; - this.implementIDictionary(this, '', System.String, valueType, accessViaMember); - - } - else { - if (this.schema.additionalProperties) { - this.ownsDictionary = true; - this.valueType = this.schema.additionalProperties === true ? System.Object : this.state.project.modelsNamespace.resolveTypeDeclaration(this.schema.additionalProperties, true, this.state); - this.modelClass.modelInterface.interfaces.push(this.implementIDictionary(this, 'additionalProperties', System.String, this.valueType)); - } - } - - return this; - } - - addSerialization() { - if (this.modelClass.jsonSerializer) { - // add serializer methods. - // this.modelClass.jsonSerializer - - - } - } - - implementIDictionary(targetClass: Class, name: string, keyType: TypeDeclaration, valueType: TypeDeclaration, accessViaMember?: Expression) { - const containerInterfaceType = { declaration: `${ClientRuntime}.IAssociativeArray<${valueType.declaration}>`, allProperties: [] }; - const dictionaryInterfaceType = System.Collections.Generic.IDictionary(keyType, valueType); - const itemType = System.Collections.Generic.KeyValuePair(keyType, valueType); - - // add the interface to the list of interfaces for the class - targetClass.interfaces.push(containerInterfaceType); - - // the backing field - const dictionaryType = System.Collections.Generic.Dictionary(keyType, valueType); - - accessViaMember = accessViaMember || targetClass.add(new Field(`__${name}`, dictionaryType, { access: Access.Protected, initialValue: dictionaryType.new() })); - - const indexer = targetClass.add(new Indexer(keyType, valueType, { get: toExpression(`${accessViaMember}[index]`), set: toExpression(`${accessViaMember}[index] = value`) })); - - // the parameters used in methods. - - const pKey = new Parameter('key', keyType); - const pValue = new Parameter('value', valueType); - const pOutValue = new Parameter('value', valueType, { modifier: ParameterModifier.Out }); - - targetClass.add(new Property(`${containerInterfaceType.declaration}.Keys`, System.Collections.Generic.IEnumerable(keyType), { get: toExpression(`${accessViaMember}.Keys`), getAccess: Access.Explicit })); - targetClass.add(new Property(`${containerInterfaceType.declaration}.Values`, System.Collections.Generic.IEnumerable(valueType), { get: toExpression(`${accessViaMember}.Values`), getAccess: Access.Explicit })); - targetClass.add(new Property(`${containerInterfaceType.declaration}.Count`, dotnet.Int, { get: toExpression(`${accessViaMember}.Count`), getAccess: Access.Explicit })); - if (name) { - targetClass.add(new ImplicitCastOperator(dictionaryType, targetClass, `source.${accessViaMember}`)); - targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}`), getAccess: Access.Explicit })); - } else { - targetClass.add(new Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: toExpression(`${accessViaMember}.AdditionalProperties`), getAccess: Access.Explicit })); - } - targetClass.add(new Method('Add', dotnet.Void, { parameters: [pKey, pValue], body: toExpression(`${accessViaMember}.Add( ${pKey}, ${pValue})`), access: Access.Public })); - targetClass.add(new Method('Clear', dotnet.Void, { body: toExpression(`${accessViaMember}.Clear()`), access: Access.Public })); - - targetClass.add(new Method('ContainsKey', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.ContainsKey( ${pKey})`), access: Access.Public })); - - targetClass.add(new Method('Remove', dotnet.Bool, { parameters: [pKey], body: toExpression(`${accessViaMember}.Remove( ${pKey})`), access: Access.Public })); - - targetClass.add(new Method('TryGetValue', dotnet.Bool, { parameters: [pKey, pOutValue], body: toExpression(`${accessViaMember}.TryGetValue( ${pKey}, out ${pOutValue})`), access: Access.Public })); - - const all = getAllVirtualProperties(this.schema.details.csharp.virtualProperties); - const exclusions = all.map(each => `"${each.name}"`).join(','); - - // add a CopyFrom that takes an IDictionary or PSObject and copies the values into this dictionary - for (const pDictType of [System.Collections.IDictionary, { declaration: 'global::System.Management.Automation.PSObject' }]) { - const pDict = new Parameter('source', pDictType); - targetClass.add(new Method('CopyFrom', dotnet.Void, { - parameters: [pDict], body: function* () { - yield If(pDict.IsNotNull, function* () { - - yield ForEach('property', ` Microsoft.Rest.ClientRuntime.PowerShell.TypeConverterExtensions.GetFilteredProperties(${pDict.value}, ${System.Collections.Generic.HashSet(System.String).new()} { ${exclusions} } )`, function* () { - - yield If(And('null != property.Key', 'null != property.Value'), function* () { - yield `this.${accessViaMember}.Add(property.Key.ToString(), global::System.Management.Automation.LanguagePrimitives.ConvertTo<${valueType.declaration}>( property.Value));`; - }); - }); - }); - } - })); - } - - // return dictionaryInterfaceType; - return containerInterfaceType; - } - - public get fileName(): string { - return `${super.fileName}.dictionary`; - } -} - export class NewDictionaryImplementation extends Class { private get state() { return this.modelClass.state; } private get schema() { return this.modelClass.schema; } diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index 5af56bcfe2..eef5a46fa1 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -24,225 +24,13 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { ModelClass, NewModelClass } from './model-class'; +import { NewModelClass } from './model-class'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; import { NewModelInterface } from './interface'; -export class JsonSerializableClass extends Class { - private btj!: Method; - private atj!: Method; - private bfj!: Method; - private afj!: Method; - private excludes: string; - - constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - this.partial = true; - this.description = modelClass.description; - this.addPartialMethods(); - - // set up the declaration for the toJson method. - const container = new Parameter('container', ClientRuntime.JsonObject, { description: `The container to serialize this object into. If the caller passes in null, a new instance will be created and returned to the caller.` }); - const mode = new Parameter('serializationMode', ClientRuntime.SerializationMode, { description: `Allows the caller to choose the depth of the serialization. See .` }); - - const toJsonMethod = this.addMethod(new Method('ToJson', ClientRuntime.JsonNode, { - parameters: [container, mode], - description: `Serializes this instance of into a .`, - returnsDescription: `a serialized instance of as a .` - })); - - // setup the declaration for the json deserializer constructor - const jsonParameter = new Parameter('json', ClientRuntime.JsonObject, { description: `A ${ClientRuntime.JsonObject} instance to deserialize from.` }); - const deserializerConstructor = this.addMethod(new Constructor(this, { - parameters: [jsonParameter], access: Access.Internal, - description: `Deserializes a ${ClientRuntime.JsonObject} into a new instance of .` - })); - - - const serializeStatements = new Statements(); - const deserializeStatements = new Statements(); - this.excludes = ''; - - if (this.modelClass.dictionaryImpl) { - const vType = this.modelClass.dictionaryImpl.valueType; - // we have to ensure that all the known wire-names are excluded on deserialization. - const exclusions = new Parameter('exclusions', System.Collections.Generic.HashSet(dotnet.String), { defaultInitializer: dotnet.Null }); - deserializerConstructor.parameters.push(exclusions); - - this.excludes = [...values(getAllProperties(this.modelClass.schema)).select(each => each.serializedName).select(each => new StringExpression(each))].join(); - this.excludes = this.excludes ? `,${System.Collections.Generic.HashSet(dotnet.String).new()}{ ${this.excludes} }` : ''; - - const ap = `((${ClientRuntime}.IAssociativeArray<${vType.declaration}>)this).AdditionalProperties`; - - if (this.modelClass.dictionaryImpl.ownsDictionary) { - // we have to implement the deserializer for it. - - serializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.ToJson( ${ap}, ${container});`)); - - if (vType === System.Object) { - // wildcard style - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); - - } else if (vType instanceof ObjectImplementation) { - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${this.modelClass.fullName}.FromJson(j) ,${exclusions.value} );`)); - } else { - deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, null ,${exclusions.value} );`)); - } - } - } - - - for (const each of values(modelClass.backingFields)) { - serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - const sch = (each.typeDeclaration).schema; - if (!(sch instanceof NewSchema) && (sch.additionalProperties)) { - deserializeStatements.add(`${each.field.value} = new ${each.className}(json${this.excludes});`); - } else { - deserializeStatements.add(`${each.field.value} = new ${each.className}(json);`); - } - } - - pushTempVar(); - for (const prop of values(modelClass.ownedProperties)) { - if (prop.details.csharp.HeaderProperty === 'Header') { - continue; - } - const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Json, prop.valuePrivate, container, prop.serializedName, mode); - - if (prop.details.csharp.readOnly) { - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); - } else { - serializeStatements.add(serializeStatement); - } - deserializeStatements.add(prop.assignPrivate((prop.type).deserializeFromContainerMember(KnownMediaType.Json, jsonParameter, prop.serializedName, prop))); - } - popTempVar(); - - const $this = this; - - // generate the implementation for toJson - toJsonMethod.add(function* () { - yield `${container} = ${container} ?? new ${ClientRuntime.JsonObject.declaration}();`; - yield EOL; - - yield 'bool returnNow = false;'; - yield `${$this.btj.name}(ref ${container}, ref returnNow);`; - - yield If(toExpression('returnNow'), `return ${container};`); - - // get serialization statements - yield serializeStatements; - - yield `${$this.atj.name}(ref ${container});`; - yield Return(container); - }); - - // and let's fill in the deserializer constructor statements now. - deserializerConstructor.add(function* () { - yield 'bool returnNow = false;'; - yield `${$this.bfj.name}(json, ref returnNow);`; - yield If(toExpression('returnNow'), 'return;'); - - yield deserializeStatements; - yield `${$this.afj.name}(json);`; - }); - } - - public get definition(): string { - const $this = this.modelClass; - // gotta write this just before we write out the class, since we had to wait until everyone had reported to their parents. - const d = this.modelClass.discriminators; - const isp = this.modelClass.isPolymorphic; - // create the FromJson method - const node = new Parameter('node', ClientRuntime.JsonNode, { description: `a to deserialize from.` }); - const fromJson = this.addMethod(new Method('FromJson', this.modelClass.modelInterface, { - parameters: [node], static: Modifier.Static, - description: `Deserializes a into an instance of ${this.modelClass.modelInterface}.`, - returnsDescription: `an instance of ${this.modelClass.modelInterface}.` - })); - - if (isp) { - fromJson.description = fromJson.description + `\n Note: the ${this.modelClass.modelInterface} interface is polymorphic, and the precise model class that will get deserialized is determined at runtime based on the payload.`; - } - const $excludes = this.excludes; - fromJson.add(function* () { - - const json = IsDeclaration(node, ClientRuntime.JsonObject, 'json'); - - if (isp) { - yield If(Not(json.check), Return(dotnet.Null)); - yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; - /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ - - if ($this.schema.discriminator) { - yield Switch(toExpression(`json.StringProperty("${$this.schema.discriminator.propertyName}")`), function* () { - for (const { key, value } of items(d)) { - yield TerminalCase(`"${key}"`, function* () { - yield Return(value.new(json)); - }); - } - }); - } - yield Return($this.new(json, toExpression($excludes.substring(1)))); - } else { - // just tell it to create the instance (providing that it's a JSonObject) - yield Return(Ternery(json.check, $this.new(json), dotnet.Null)); - } - }); - - return super.definition; - } - - public get fileName(): string { - return `${super.fileName}.json`; - } - - protected addPartialMethods() { - // add partial methods for future customization - this.btj = this.addMethod(new PartialMethod('BeforeToJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }), - ], - description: `BeforeToJson will be called before the json serialization has commenced, allowing complete customization of the object before it is serialized. - If you wish to disable the default serialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.atj = this.addMethod(new PartialMethod('AfterToJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', ClientRuntime.JsonObject, { modifier: ParameterModifier.Ref, description: 'The JSON container that the serialization result will be placed in.' }), - ], - description: `AfterToJson will be called after the json erialization has finished, allowing customization of the before it is returned. Implement this method in a partial class to enable this behavior ` - })); - - this.bfj = this.addMethod(new PartialMethod('BeforeFromJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the deserialization should be processed, or if the method should return instantly.' }), - ], - description: `BeforeFromJson will be called before the json deserialization has commenced, allowing complete customization of the object before it is deserialized. - If you wish to disable the default deserialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afj = this.addMethod(new PartialMethod('AfterFromJson', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('json', ClientRuntime.JsonObject, { description: 'The JsonNode that should be deserialized into this object.' }), - ], - description: 'AfterFromJson will be called after the json deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ' - })); - } -} export class NewJsonSerializableClass extends Class { private btj!: Method; @@ -251,7 +39,7 @@ export class NewJsonSerializableClass extends Class { private afj!: Method; private excludes: string; - constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { + constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { super(modelClass.namespace, modelClass.name); this.apply(objectInitializer); this.partial = true; diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index 9ba766976a..be20242473 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -23,16 +23,14 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { ModelClass } from './model-class'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelProperty } from './property'; import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; -import { getVirtualPropertyName, NewGetVirtualPropertyName } from './model-class'; +import { NewGetVirtualPropertyName } from './model-class'; import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; export class SerializationPartialClass extends Initializer { @@ -108,116 +106,11 @@ export class NewSerializationPartialClass extends Initializer { } } -export class DeserializerPartialClass extends SerializationPartialClass { - private beforeDeserialize!: Method; - private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); - this.apply(objectInitializer); - } - - async init() { - // add partial methods for extensibility - this.addPartialMethods(); - this.addDeserializerConstructor(); - this.addDeserializerMethod(); - } - - protected addDeserializerConstructor() { - const $this = this; - - const deserializerConstructor = this.targetClass.addMethod(new Constructor(this.targetClass, { - parameters: [this.contentParameter], access: Access.Internal, - description: `Deserializes a ${this.typeCref} into a new instance of ${this.thisCref}.` - })); - - deserializerConstructor.add(function* () { - const returnNow = new LocalVariable('returnNow', dotnet.Bool, { initializer: dotnet.False }); - yield returnNow.declarationStatement; - - yield `${$this.beforeDeserialize.name}(${$this.contentParameter}, ref ${returnNow.value});`; - yield If(returnNow, 'return;'); - yield $this.deserializeStatements; - if ($this.hasAadditionalProperties($this.schema)) { - // this type has an additional properties dictionary - yield '// this type is a dictionary; copy elements from source to here.'; - yield `CopyFrom(${$this.contentParameter.value});`; - } - - yield `${$this.afterDeserialize.name}(${$this.contentParameter});`; - }); - } - - private hasAadditionalProperties(aSchema: Schema): boolean { - if (aSchema.additionalProperties) { - return true; - } else - for (const each of values(aSchema.allOf)) { - const r = this.hasAadditionalProperties(each); - if (r) { - return r; - } - } - return false; - } - - get deserializeStatements() { - const $this = this; - - return function* () { - yield '// actually deserialize '; - - for (const virtualProperty of values($this.allVirtualProperties)) { - // yield `// deserialize ${virtualProperty.name} from ${$this.serializationFormat}`; - const type = $this.resolver(virtualProperty.property.schema, virtualProperty.property.details.default.required); - - const cvt = type.convertObjectMethod; - const t = `((${virtualProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - const tt = type ? `(${type.declaration})` : ''; - - yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; - } - }; - } - - protected addDeserializerMethod() { - const $this = this; - - const deserialzeMethod = this.targetClass.addMethod(new Method(`DeserializeFrom${this.serializationFormat}`, this.targetInterface, { - parameters: [this.contentParameter], static: Modifier.Static, - description: `Deserializes a ${this.typeCref} into an instance of ${this.thisCref}.`, - returnsDescription: `an instance of ${this.interfaceCref}.` - })); - - deserialzeMethod.add(function* () { - yield Return($this.targetClass.new($this.contentParameter)); - }); - - } - - protected addPartialMethods() { - const before = `BeforeDeserialize${this.serializationFormat}`; - const after = `AfterDeserialize${this.serializationFormat}`; - this.beforeDeserialize = this.targetClass.addMethod(new PartialMethod(before, dotnet.Void, { - access: Access.Default, - parameters: [this.contentParameter, this.returnNowParameter], - description: `${before} will be called before the deserialization has commenced, allowing complete customization of the object before it is deserialized. - If you wish to disable the default deserialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afterDeserialize = this.targetClass.addMethod(new PartialMethod(after, dotnet.Void, { - access: Access.Default, - parameters: [this.contentParameter], - description: `${after} will be called after the deserialization has finished, allowing customization of the object before it is returned. Implement this method in a partial class to enable this behavior ` - })); - } -} export class NewDeserializerPartialClass extends NewSerializationPartialClass { private beforeDeserialize!: Method; private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/model/model-class-xml.ts b/powershell/llcsharp/model/model-class-xml.ts deleted file mode 100644 index 831158e974..0000000000 --- a/powershell/llcsharp/model/model-class-xml.ts +++ /dev/null @@ -1,174 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { KnownMediaType, HeaderProperty, HeaderPropertyType } from '@azure-tools/codemodel-v3'; -import { EOL, DeepPartial } from '@azure-tools/codegen'; -import { items, values } from '@azure-tools/linq'; - -import { Access, Class, Constructor, dotnet, If, IsDeclaration, Method, Modifier, Not, Parameter, ParameterModifier, PartialMethod, Return, Statements, Switch, System, TerminalCase, Ternery } from '@azure-tools/codegen-csharp'; -import { ClientRuntime } from '../clientruntime'; -import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { popTempVar, pushTempVar } from '../schema/primitive'; -import { ModelClass } from './model-class'; - -import { ModelProperty } from './property'; - -export class XmlSerializableClass extends Class { - private btj!: Method; - private atj!: Method; - private bfj!: Method; - private afj!: Method; - - constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { - super(modelClass.namespace, modelClass.name); - this.apply(objectInitializer); - this.partial = true; - - this.addPartialMethods(); - - // set up the declaration for the toXml method. - const container = new Parameter('container', System.Xml.Linq.XElement, { description: `The container to serialize this object into. If the caller passes in null, a new instance will be created and returned to the caller.` }); - const mode = new Parameter('serializationMode', ClientRuntime.SerializationMode, { description: `Allows the caller to choose the depth of the serialization. See .` }); - - const toXmlMethod = this.addMethod(new Method('ToXml', System.Xml.Linq.XElement, { - parameters: [container, mode], - })); - - // setup the declaration for the xml deserializer constructor - const xmlParameter = new Parameter('xml', System.Xml.Linq.XElement, { description: `A ${System.Xml.Linq.XElement} instance to deserialize from.` }); - const deserializerConstructor = this.addMethod(new Constructor(this, { - parameters: [xmlParameter], access: Access.Internal, - description: `Deserializes a ${System.Xml.Linq.XElement} into a new instance of .` - })); - - const serializeStatements = new Statements(); - const deserializeStatements = new Statements(); - - for (const each of values(modelClass.backingFields)) { - serializeStatements.add(`${each.field.value}?.ToXml(result, ${mode.use});`); - deserializeStatements.add(`${each.field.value} = new ${each.className}(xml);`); - } - pushTempVar(); - for (const property of values(modelClass.schema.properties)) { - const prop = modelClass.$(property.details.csharp.name); - const serializeStatement = (prop.type).serializeToContainerMember(KnownMediaType.Xml, prop, container, prop.serializedName, mode); - - if (property.details.csharp[HeaderProperty] === HeaderPropertyType.Header) { - // it's a header only property. Don't serialize unless the mode has SerializationMode.IncludeHeaders enabled - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeHeaders})`, serializeStatement)); - } else { - if (property.details.csharp.readOnly) { - serializeStatements.add(If(`${mode.use}.HasFlag(${ClientRuntime.SerializationMode.IncludeReadOnly})`, serializeStatement)); - } else { - serializeStatements.add(serializeStatement); - } - } - deserializeStatements.add(prop.assignPrivate((prop.type).deserializeFromContainerMember(KnownMediaType.Xml, xmlParameter, prop.serializedName, prop))); - } - popTempVar(); - const $this = this; - - // generate the implementation for toXml - toXmlMethod.add(function* () { - yield `${container} = ${container} ?? new ${System.Xml.Linq.XElement.declaration}(nameof(${$this.modelClass.name}));`; - yield EOL; - - yield 'bool returnNow = false;'; - yield `${$this.btj.name}(ref ${container}, ref returnNow);`; - - yield If('returnNow', `return ${container};`); - - // get serialization statements - yield serializeStatements; - - yield `${$this.atj.name}(ref ${container});`; - yield Return(container); - }); - - // and let's fill in the deserializer constructor statements now. - deserializerConstructor.add(function* () { - yield 'bool returnNow = false;'; - yield `${$this.bfj.name}(xml, ref returnNow);`; - yield If('returnNow', 'return;'); - - yield deserializeStatements; - yield `${$this.afj.name}(xml);`; - }); - } - - public get definition(): string { - const $this = this.modelClass; - // gotta write this just before we write out the class, since we had to wait until everyone had reported to their parents. - const d = this.modelClass.discriminators; - const isp = this.modelClass.isPolymorphic; - // create the FromXml method - const node = new Parameter('node', System.Xml.Linq.XElement, { description: `A ${System.Xml.Linq.XElement} instance to deserialize from.` }); - const fromXml = this.addMethod(new Method('FromXml', this.modelClass.modelInterface, { parameters: [node], static: Modifier.Static })); - fromXml.add(function* () { - - const xml = IsDeclaration(node, System.Xml.Linq.XElement, 'xml'); - - if (isp) { - yield If(Not(xml.check), Return(dotnet.Null)); - yield '// Polymorphic type -- select the appropriate constructor using the discriminator'; - /** go thru the list of polymorphic values for the discriminator, and call the target class's constructor for that */ - - if ($this.schema.discriminator) { - yield Switch(`xml.StringProperty("${$this.schema.discriminator.propertyName}")`, function* () { - for (const { key, value } of items(d)) { - yield TerminalCase(`"${key}"`, function* () { - yield Return(value.new(xml)); - }); - } - }); - } - yield Return($this.new(xml)); - } else { - // just tell it to create the instance (providing that it's a XElement) - yield Return(Ternery(xml.check, $this.new(xml), dotnet.Null)); - } - }); - - return super.definition; - } - - public get fileName(): string { - return `${super.fileName}.xml`; - } - - protected addPartialMethods() { - // add partial methods for future customization - this.btj = this.addMethod(new PartialMethod('BeforeToXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', System.Xml.Linq.XElement, { modifier: ParameterModifier.Ref, description: 'The XElement that the serialization result will be placed in.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }), - ], - })); - - this.atj = this.addMethod(new PartialMethod('AfterToXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('container', System.Xml.Linq.XElement, { modifier: ParameterModifier.Ref, description: 'The XElement that the serialization result will be placed in.' }), - ], - })); - - this.bfj = this.addMethod(new PartialMethod('BeforeFromXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('xml', System.Xml.Linq.XElement, { description: 'The XmlNode that should be deserialized into this object.' }), - new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the deserialization should be processed, or if the method should return instantly.' }), - ], - })); - - this.afj = this.addMethod(new PartialMethod('AfterFromXml', dotnet.Void, { - access: Access.Default, - parameters: [ - new Parameter('xml', System.Xml.Linq.XElement, { description: 'The XmlNode that should be deserialized into this object.' }), - ], - })); - } - -} diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index c87075ae1b..5a420b37a3 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -8,26 +8,18 @@ import { camelCase, deconstruct, DeepPartial } from '@azure-tools/codegen'; import { items, values } from '@azure-tools/linq'; import { Access, Class, Constructor, Expression, ExpressionOrLiteral, Field, If, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Statements, System, TypeDeclaration, valueOf, Variable, BackedProperty, Property, Virtual, toExpression, StringExpression, LiteralExpression, Attribute } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { ModelInterface, NewModelInterface } from './interface'; -import { JsonSerializableClass, NewJsonSerializableClass } from './model-class-json'; -import { ModelProperty, NewModelProperty } from './property'; +import { NewModelInterface } from './interface'; +import { NewJsonSerializableClass } from './model-class-json'; +import { NewModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; -import { DictionaryImplementation, NewDictionaryImplementation } from './model-class-dictionary'; +import { NewDictionaryImplementation } from './model-class-dictionary'; import { Languages, Language, Schema as NewSchema, SchemaType, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; import { VirtualProperty as NewVirtualProperty, getAllVirtualProperties as newGetAllVirtualProperties } from '../../utils/schema'; -export function getVirtualPropertyName(vp?: VirtualProperty): string { - - if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { - return getVirtualPropertyName(vp.accessViaMember); - } - return vp ? vp.name : ''; -} - export function NewGetVirtualPropertyName(vp?: NewVirtualProperty): string { if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { @@ -42,467 +34,6 @@ export interface BackingField { className: string; } -export class ModelClass extends Class implements EnhancedTypeDeclaration { - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); - } - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return this.featureImplementation.deserializeFromNode(mediaType, node, defaultValue); - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return this.featureImplementation.serializeToNode(mediaType, value, serializedName, mode); - } - - get defaultOfType() { - return toExpression('null /* model class */'); - } - - get convertObjectMethod() { - return this.featureImplementation.convertObjectMethod; - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return this.featureImplementation.serializeToContent(mediaType, value, mode); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.featureImplementation.deserializeFromString(mediaType, content, defaultValue); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return this.featureImplementation.deserializeFromResponse(mediaType, content, defaultValue); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.featureImplementation.serializeToContainerMember(mediaType, value, container, serializedName, mode); - } - - get isXmlAttribute(): boolean { - return this.featureImplementation.isXmlAttribute; - } - - public isNullable = true; - - get isRequired(): boolean { - return this.featureImplementation.isRequired; - } - - public isPolymorphic = false; - public get schema() { return this.featureImplementation.schema; } - - /* @internal */ validateMethod?: Method; - /* @internal */ discriminators: Map = new Map(); - /* @internal */ parentModelClasses: Array = new Array(); - /* @internal */ get modelInterface(): ModelInterface { return this.schema.details.csharp.interfaceImplementation; } - /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.details.csharp.internalInterfaceImplementation; } - - /* @internal */ state: State; - /* @internal */ backingFields = new Array(); - /* @internal */ featureImplementation: ObjectImplementation; - /* @internal */ validationEventListener: Parameter = new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive validation events.` }); - /* @internal */ jsonSerializer?: JsonSerializableClass; - // /* @internal */ xmlSerializer?: XmlSerializableClass; - /* @internal */ dictionaryImpl?: DictionaryImplementation; - - private readonly validationStatements = new Statements(); - public ownedProperties = new Array(); - private pMap = new Map(); - - // public hasHeaderProperties: boolean; - - constructor(namespace: Namespace, schemaWithFeatures: ObjectImplementation, state: State, objectInitializer?: DeepPartial) { - super(namespace, schemaWithFeatures.schema.details.csharp.name); - this.featureImplementation = schemaWithFeatures; - this.schema.details.csharp.classImplementation = this; // mark the code-model with the class we're creating. - this.state = state; - this.apply(objectInitializer); - - if (this.state.getValue('powershell') && this.schema.details.csharp.suppressFormat) { - this.add(new Attribute(DoNotFormatAttribute)); - } - - // must be a partial class - this.partial = true; - - this.handleDiscriminator(); - - // create an interface for this model class - if (!this.schema.details.csharp.interfaceImplementation) { - (this.schema.details.csharp.interfaceImplementation = new ModelInterface(this.namespace, this.schema.details.csharp.interfaceName || `I${this.schema.details.csharp.name}`, this, this.state)); - - } - this.interfaces.push(this.modelInterface); - - if (!this.schema.details.csharp.internalInterfaceImplementation) { - (this.schema.details.csharp.internalInterfaceImplementation = new ModelInterface(this.namespace, this.schema.details.csharp.internalInterfaceName || `I${this.schema.details.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); - - } - - this.interfaces.push(this.internalModelInterface); - - this.schema.details.csharp.internalInterfaceImplementation.init(); - this.schema.details.csharp.interfaceImplementation.init(); - - // add default constructor - this.addMethod(new Constructor(this, { description: `Creates an new instance.` })); // default constructor for fits and giggles. - - // handle parent interface implementation - if (!this.handleAllOf()) { - // handle the AdditionalProperties if used - if (this.schema.additionalProperties) { - this.dictionaryImpl = new DictionaryImplementation(this).init(); - } - } - - // create the properties for ths schema - this.createProperties(); - - // add validation implementation - this.addValidation(); - - // add header properties for this model. - // DISABLED. - this.addHeaderDeserializer(); - - if (this.state.project.jsonSerialization) { - this.jsonSerializer = new JsonSerializableClass(this); - } - } - - private nested(virtualProperty: VirtualProperty, internal: boolean): string { - if (virtualProperty.accessViaProperty) { - if (virtualProperty.accessViaProperty.accessViaProperty) { - // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - } - } - //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - } - - private accessor(virtualProperty: VirtualProperty, internal = false): string { - if (virtualProperty.accessViaProperty) { - const prefix = virtualProperty.accessViaProperty.accessViaProperty ? this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal) : ''; - const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); - if (containingProperty && virtualProperty.accessViaMember) { - //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - } - } - // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; - return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; - } - - private createProperties() { - // generate a protected backing field for each - // and then expand the nested properties into this class forwarding to the member. - - // add properties - if (this.schema.details.csharp.virtualProperties) { - const addFormatAttributesToProperty = (property: Property, virtualProperty: VirtualProperty) => { - if (virtualProperty.format) { - if (virtualProperty.format.suppressFormat) { - property.add(new Attribute(DoNotFormatAttribute)); - } else { - const parameters = []; - if (virtualProperty.format.index !== undefined) { - parameters.push(`Index = ${virtualProperty.format.index}`); - } - - if (virtualProperty.format.label !== undefined) { - parameters.push(`Label = ${new StringExpression(virtualProperty.format.label)}`); - } - - if (virtualProperty.format.width !== undefined) { - parameters.push(`Width = ${virtualProperty.format.width}`); - } - - property.add(new Attribute(FormatTableAttribute, { parameters })); - } - } - }; - - /* Owned Properties */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.owned)) { - const actualProperty = virtualProperty.property; - let n = 0; - const decl = this.state.project.modelsNamespace.resolveTypeDeclaration(actualProperty.schema, actualProperty.details.csharp.required, this.state.path('schema')); - - /* public property */ - const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.details.csharp.required, actualProperty.serializedName, actualProperty.details.csharp.description, this.state.path('properties', n++), { - initializer: actualProperty.details.csharp.constantValue ? typeof actualProperty.details.csharp.constantValue === 'string' ? new StringExpression(actualProperty.details.csharp.constantValue) : new LiteralExpression(actualProperty.details.csharp.constantValue) : undefined - }); - - if (actualProperty.details.csharp.readOnly) { - myProperty.set = undefined; - } - myProperty.details = virtualProperty.property.details; - - if (actualProperty.details.csharp.constantValue !== undefined) { - myProperty.setAccess = Access.Internal; - myProperty.set = undefined; - } - - if (virtualProperty.private) { - // when properties are inlined, the container accessor can be internalized. I think. - myProperty.setAccess = Access.Internal; - myProperty.getAccess = Access.Internal; - this.pMap.set(virtualProperty, myProperty); - } - - this.ownedProperties.push(this.add(myProperty)); - - if (myProperty.getAccess !== Access.Public || myProperty.setAccess !== Access.Public || myProperty.set === undefined) { - /* internal interface property */ - - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, decl, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: myProperty.get, - set: myProperty.assignPrivate('value') - })); - } - - if (this.state.getValue('powershell')) { - myProperty.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Owned`] })); - addFormatAttributesToProperty(myProperty, virtualProperty); - } - } - - /* Inherited properties. */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inherited)) { - // so each parent property that is getting exposed - // has to be accessed via the field in this.backingFields - const parentField = this.backingFields.find(each => virtualProperty.accessViaSchema ? virtualProperty.accessViaSchema.details.csharp.interfaceImplementation.fullName === each.typeDeclaration.declaration : false); - - const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - const opsType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.originalContainingSchema, false, this.state); - const via = virtualProperty.accessViaProperty; - const parentCast = `(${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName})`; - const vp = this.add(new Property(virtualProperty.name, propertyType, { - description: virtualProperty.property.details.csharp.description, - get: toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)}`), - set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`(${parentCast}${parentField.field.name}).${this.accessor(virtualProperty)} = value`) - })); - - if (virtualProperty.property.details.csharp.constantValue !== undefined) { - vp.setAccess = Access.Internal; - vp.set = undefined; - } - - if (vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: toExpression(`(${parentCast}${parentField.field.name}).${via.name}`), - set: toExpression(`(${parentCast}${parentField.field.name}).${via.name} = value`) - })); - } - - if (this.state.getValue('powershell')) { - vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inherited`] })); - addFormatAttributesToProperty(vp, virtualProperty); - } - } - - /* Inlined properties. */ - for (const virtualProperty of values(this.schema.details.csharp.virtualProperties.inlined)) { - if (virtualProperty.private) { - // continue; - // can't remove it, it has to be either public or internally implemented. - } - - if (virtualProperty.accessViaProperty) { - const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); - if (containingProperty) { - - const propertyType = this.state.project.modelsNamespace.resolveTypeDeclaration(virtualProperty.property.schema, virtualProperty.property.details.csharp.required, this.state); - - // regular inlined property - const vp = new Property(virtualProperty.name, propertyType, { - description: virtualProperty.property.details.csharp.description, - get: toExpression(`${this.accessor(virtualProperty)}`), - set: (virtualProperty.property.details.csharp.readOnly || virtualProperty.property.details.csharp.constantValue) ? undefined : toExpression(`${this.accessor(virtualProperty)} = value`) - }); - - if (!virtualProperty.private) { - this.add(vp); - } - - if (virtualProperty.private || vp.getAccess !== Access.Public || vp.setAccess !== Access.Public || vp.set === undefined) { - this.add(new Property(`${virtualProperty.originalContainingSchema.details.csharp.internalInterfaceImplementation.fullName}.${virtualProperty.name}`, propertyType, { - description: `Internal Acessors for ${virtualProperty.name}`, - getAccess: Access.Explicit, - setAccess: Access.Explicit, - get: vp.get, - set: toExpression(`${this.accessor(virtualProperty)} = value`) - })); - } - - if (virtualProperty.property.details.csharp.constantValue !== undefined) { - vp.setAccess = Access.Internal; - vp.set = undefined; - } - - if (this.state.getValue('powershell')) { - vp.add(new Attribute(PropertyOriginAttribute, { parameters: [`${this.state.project.serviceNamespace}.PropertyOrigin.Inlined`] })); - addFormatAttributesToProperty(vp, virtualProperty); - } - } - } - } - - } - } - - private addValidation() { - if (this.validationStatements.implementation.trim()) { - // we do have something to valdiate! - - // add the IValidates implementation to this object. - this.interfaces.push(ClientRuntime.IValidates); - this.validateMethod = this.addMethod(new Method('Validate', System.Threading.Tasks.Task(), { - async: Modifier.Async, - parameters: [this.validationEventListener], - description: 'Validates that this object meets the validation criteria.', - returnsDescription: `A < see cref = "${System.Threading.Tasks.Task()}" /> that will be complete when validation is completed.` - })); - this.validateMethod.add(this.validationStatements); - } - } - - private additionalPropertiesType(aSchema: Schema): TypeDeclaration | undefined { - if (aSchema.additionalProperties) { - - if (aSchema.additionalProperties === true) { - return System.Object; - - } else { - // we're going to implement IDictionary - return this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema.additionalProperties, true, this.state); - } - } else - for (const each of values(aSchema.allOf)) { - const r = this.additionalPropertiesType(each); - if (r) { - return r; - } - } - return undefined; - } - - private handleAllOf() { - let hasAdditionalPropertiesInParent = false; - // handle s - // add an 'implements' for the interface for the allOf. - for (const { key: eachSchemaIndex, value: eachSchemaValue } of items(this.schema.allOf)) { - const aSchema = eachSchemaValue; - const aState = this.state.path('allOf', eachSchemaIndex); - - const td = this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema, true, aState); - const parentClass = (aSchema.details.csharp.classImplementation); - const className = parentClass.fullName; - const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); - - // add the interface as a parent to our interface. - const iface = aSchema.details.csharp.interfaceImplementation; - - // add a field for the inherited values - const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); - this.backingFields.push({ - className, - typeDeclaration: td, - field: backingField - }); - this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); - this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); - - this.internalModelInterface.interfaces.push(aSchema.details.csharp.internalInterfaceImplementation); - this.modelInterface.interfaces.push(iface); - - // - const addlPropType = this.additionalPropertiesType(aSchema); - if (addlPropType) { - this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); - hasAdditionalPropertiesInParent = true; - } - } - return hasAdditionalPropertiesInParent; - } - - private handleDiscriminator() { - if (this.schema.discriminator) { - // this has a discriminator property. - // our children are expected to tell us who they are - this.isPolymorphic = true; - // we'll add a deserializer factory method a bit later.. - } - - if (this.schema.details.csharp.discriminatorValue) { - // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. - // um. just how do we *really* know which allOf is polymorphic? - // that's really sad. - for (const { key: eachAllOfIndex, value: eachAllOfValue } of items(this.schema.allOf)) { - const parentSchema = eachAllOfValue; - const aState = this.state.path('allOf', eachAllOfIndex); - - // ensure the parent schema has it's class created first. - this.state.project.modelsNamespace.resolveTypeDeclaration(parentSchema, true, aState); - - const parentClass = parentSchema.details.csharp.classImplementation; - if (parentClass.isPolymorphic) { - // remember this class for later. - this.parentModelClasses.push(parentClass); - - // tell that parent who we are. - parentClass.addDiscriminator(this.schema.details.csharp.discriminatorValue, this); - } - } - } - } - private addHeaderDeserializer() { - const avp = getAllVirtualProperties(this.schema.details.csharp.virtualProperties); - const headers = new Parameter('headers', System.Net.Http.Headers.HttpResponseHeaders); - const readHeaders = new Method(`${ClientRuntime.IHeaderSerializable}.ReadHeaders`, undefined, { - access: Access.Explicit, - parameters: [headers], - }); - - let used = false; - - for (const headerProperty of values(avp).where(each => each.property.details.csharp[HeaderProperty] === HeaderPropertyType.HeaderAndBody || each.property.details.csharp[HeaderProperty] === HeaderPropertyType.Header)) { - used = true; - const t = `((${headerProperty.originalContainingSchema.details.csharp.fullInternalInterfaceName})this)`; - const values = `__${camelCase([...deconstruct(headerProperty.property.serializedName), 'Header'])}`; - const td = this.state.project.modelsNamespace.resolveTypeDeclaration(headerProperty.property.schema, false, this.state.path('schema')); - readHeaders.add(If(`${valueOf(headers)}.TryGetValues("${headerProperty.property.serializedName}", out var ${values})`, `${t}.${headerProperty.name} = ${td.deserializeFromContainerMember(KnownMediaType.Header, headers, values, td.defaultOfType)};`)); - } - if (used) { - this.interfaces.push(ClientRuntime.IHeaderSerializable); - this.add(readHeaders); - } - } - - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.featureImplementation.validateValue(eventListener, property); - } - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return this.featureImplementation.validatePresence(eventListener, property); - } - - public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { - this.discriminators.set(discriminatorValue, modelClass); - - // tell any polymorphic parents incase we're doing subclass of a subclass. - for (const each of this.parentModelClasses) { - each.addDiscriminator(discriminatorValue, modelClass); - } - } -} - export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); @@ -571,7 +102,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // public hasHeaderProperties: boolean; - constructor(namespace: Namespace, schemaWithFeatures: NewObjectImplementation, state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, schemaWithFeatures: NewObjectImplementation, state: NewState, objectInitializer?: DeepPartial) { super(namespace, schemaWithFeatures.schema.language.csharp?.name || ''); this.featureImplementation = schemaWithFeatures; this.schema.language.csharp = this.schema.language.csharp || new Language(); @@ -873,12 +404,12 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const aState = this.state.path('allOf', eachSchemaIndex); const td = this.state.project.modelsNamespace.NewResolveTypeDeclaration(aSchema, true, aState); - const parentClass = (aSchema.language.csharp?.classImplementation); + const parentClass = (aSchema.language.csharp?.classImplementation); const className = parentClass.fullName; const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); // add the interface as a parent to our interface. - const iface = aSchema.language.csharp?.interfaceImplementation; + const iface = aSchema.language.csharp?.interfaceImplementation; // add a field for the inherited values const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); @@ -890,7 +421,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); - this.internalModelInterface.interfaces.push(aSchema.language.csharp?.internalInterfaceImplementation); + this.internalModelInterface.interfaces.push(aSchema.language.csharp?.internalInterfaceImplementation); this.modelInterface.interfaces.push(iface); // diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 58d0d0d64a..f6e2bdfe75 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -8,15 +8,15 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../schema/schema-resolver'; -import { EnumClass, NewEnumClass } from '../enums/enum'; +import { NewSchemaDefinitionResolver } from '../schema/schema-resolver'; +import { NewEnumClass } from '../enums/enum'; import * as validation from '../validations'; -import { ModelInterface, NewModelInterface } from './interface'; -import { ModelClass, NewModelClass } from './model-class'; +import { NewModelInterface } from './interface'; +import { NewModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -32,138 +32,12 @@ class ApiVersionNamespace extends Namespace { } } -export class ModelsNamespace extends Namespace { - private subNamespaces = new Dictionary(); - - resolver = new SchemaDefinitionResolver(); - newResolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary | NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { - super('Models', parent); - this.subNamespaces[this.fullName] = this; - - - this.apply(objectInitializer); - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // special case... hook this up before we get anywhere. - state.project.modelsNamespace = this; - if (!(schemas instanceof NewSchemas)) { - for (const { key: index, value: schema } of items(schemas)) { - const state = this.state.path(index); - - // verify that the model isn't in a bad state - if (validation.objectWithFormat(schema, state)) { - continue; - } - this.resolveTypeDeclaration(schema, true, state); - } - } else { - if (schemas.objects) { - for (const schema of schemas.objects) { - this.NewResolveTypeDeclaration(schema, true, state); - } - } - if (schemas.strings) { - for (const schema of schemas.strings) { - this.NewResolveTypeDeclaration(schema, true, state); - } - } - //todo, need to add support for other types - } - } - - get outputFolder() { - return 'Models'; - } - - public resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: State): EnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - const td = this.resolver.resolveTypeDeclaration(schema, required, state); - - if (!schema.details.csharp.skip) { - if (td instanceof ObjectImplementation) { - // it's a class object. - // create it if necessary - - const fullname = schema.details.csharp.namespace || this.fullName; - - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - - const mc = schema.details.csharp.classImplementation || new ModelClass(ns, td, this.state, { description: schema.details.csharp.description }); - - // this gets implicity created during class creation: - return schema.details.csharp.interfaceImplementation; - } - - if (state.project.azure && /^api-?version$/i.exec(schema.details.csharp.name)) { - return td; - } - - if (td instanceof EnumImplementation) { - if (schema.details.csharp.enum) { - const ec = state.project.supportNamespace.findClassByName(schema.details.csharp.enum.name); - if (length(ec) === 0) { - new EnumClass(td, state); - // return schema.details.csharp.typeDeclaration = ec[0]; - } - } - - return schema.details.csharp.typeDeclaration = td; - } - } - return td; - } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - const td = this.newResolver.resolveTypeDeclaration(schema, required, state); - - if (!schema.language.csharp?.skip) { - if (td instanceof NewObjectImplementation) { - // it's a class object. - // create it if necessary - - const fullname = schema.language.csharp?.namespace || this.fullName; - - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - - const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); - - // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; - } - - if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { - return td; - } - - if (td instanceof NewEnumImplementation) { - if (schema.language.csharp?.enum) { - const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); - if (length(ec) === 0) { - new NewEnumClass(td, state); - // return schema.language.csharp.typeDeclaration = ec[0]; - } - } - schema.language.csharp = schema.language.csharp || new Language(); - return schema.language.csharp.typeDeclaration = td; - } - } - return td; - } -} - export class NewModelsNamespace extends Namespace { private subNamespaces = new Dictionary(); - resolver = new SchemaDefinitionResolver(); + resolver = new NewSchemaDefinitionResolver(); newResolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: NewSchemas, private state: State | NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private schemas: NewSchemas, private state: NewState, objectInitializer?: DeepPartial) { super('Models', parent); this.subNamespaces[this.fullName] = this; diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index 014eee8294..c17561d301 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -14,75 +14,10 @@ import { EnhancedVariable } from '../extended-variable'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; -import { ModelClass } from './model-class'; +import { NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; -export class ModelProperty extends BackedProperty implements EnhancedVariable { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, container, this, serializedName, mode); - } - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - if (this.required) { - return (this.type).validatePresence(eventListener, this); - } - return ''; - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return (this.type).validateValue(eventListener, this); - } - - private required: boolean; - // DISABLED - // public IsHeaderProperty: boolean; - public schema: Schema; - public serializedName: string; - private typeDeclaration: EnhancedTypeDeclaration; - public details: any; - - constructor(name: string, schema: Schema, isRequired: boolean, serializedName: string, description: string, state: State, objectInitializer?: DeepPartial) { - const decl = state.project.modelsNamespace.resolveTypeDeclaration(schema, isRequired, state.path('schema')); - super(name, decl); - this.typeDeclaration = decl; - this.serializedName = serializedName; - this.schema = schema; - if (this.schema.readOnly) { - this.set = undefined; - } - this.apply(objectInitializer); - this.description = description; - this.required = isRequired; - if (this.schema.type === JsonType.Object && isAnExpression(this.get) && schema.details.csharp.classImplementation) { - // for objects, the getter should auto-create a new object - this.get = toExpression(`(${this.get.value} = ${this.get.value} ?? new ${schema.details.csharp.fullname}())`); - } - } - - -} - export class NewModelProperty extends BackedProperty implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { @@ -126,7 +61,7 @@ export class NewModelProperty extends BackedProperty implements EnhancedVariable private typeDeclaration: NewEnhancedTypeDeclaration; public language: any; - constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: NewState, objectInitializer?: DeepPartial) { const decl = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, isRequired, state.path('schema')); super(name, decl); this.typeDeclaration = decl; diff --git a/powershell/llcsharp/operation/api-class.ts b/powershell/llcsharp/operation/api-class.ts index 34aa980a8b..86a06dbc78 100644 --- a/powershell/llcsharp/operation/api-class.ts +++ b/powershell/llcsharp/operation/api-class.ts @@ -6,79 +6,50 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Class, Namespace } from '@azure-tools/codegen-csharp'; -import { State, NewState } from '../generator'; -import { CallMethod, OperationMethod, NewOperationMethod, ValidationMethod, NewCallMethod, NewValidationMethod } from '../operation/method'; +import { NewState } from '../generator'; +import { NewOperationMethod, NewCallMethod, NewValidationMethod } from '../operation/method'; import { ParameterLocation } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; export class ApiClass extends Class { // protected sender: Property; - constructor(namespace: Namespace, protected state: State | NewState, objectInitializer?: DeepPartial) { - super(namespace, (state instanceof NewState) ? state.model.language.csharp?.name || '' : state.model.details.csharp.name); + constructor(namespace: Namespace, protected state: NewState, objectInitializer?: DeepPartial) { + super(namespace, state.model.language.csharp?.name || ''); this.apply(objectInitializer); // add basics // this.sender = this.add(new Property("Sender", ClientRuntime.ISendAsync)); // add operations from code model - if (!(state instanceof NewState)) { - for (const { key: operationIndex, value: operation } of items(state.model.http.operations)) { - // an operation has parameters for parameters, body, callbacks, listener and sender - // we need to make sure that the parameters for a given operation are consistent between the operation method, the call method, and the validation method. - // can we generate the common parameters here and just give them to the methods? (ie, can we share the instances between the methods?) - // code-dom doesn't store references from the child to the parent, so as long as the definitions work without modification, it looks like we can. - // we'll do that work in the OM and expose them as public properties. - const operationMethod = new OperationMethod(this, operation, false, state.path('components', 'operations', operationIndex)); + // todo + for (const operationGroup of state.model.operationGroups) { + for (const operation of operationGroup.operations) { + const operationMethod = new NewOperationMethod(this, operation, false, state); this.addMethod(operationMethod); - if ([...values(operation.parameters).select(each => each.in === ParameterLocation.Path)].length > 0) { + // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it + const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); + if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new OperationMethod(this, operation, true, state.path('components', 'operations', operationIndex)); + const identityMethod = new NewOperationMethod(this, operation, true, state); identityMethod.emitCall(false); this.addMethod(identityMethod); } // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new CallMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + const cm = new NewCallMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(cm)) { this.addMethod(cm); } - const vm = new ValidationMethod(this, operationMethod, state.path('components', 'operations', operationIndex)); + const vm = new NewValidationMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(vm)) { this.addMethod(vm); } } - } else { - // todo - for (const operationGroup of state.model.operationGroups) { - for (const operation of operationGroup.operations) { - const operationMethod = new NewOperationMethod(this, operation, false, state); - this.addMethod(operationMethod); - // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it - const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); - if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { - // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new NewOperationMethod(this, operation, true, state); - identityMethod.emitCall(false); - this.addMethod(identityMethod); - } - - // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new NewCallMethod(this, operationMethod, state); - if (!this.hasMethodWithSameDeclaration(cm)) { - this.addMethod(cm); - } - - const vm = new NewValidationMethod(this, operationMethod, state); - if (!this.hasMethodWithSameDeclaration(vm)) { - this.addMethod(vm); - } - } - } } } } diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 127dc877cc..9911aec1d0 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -24,18 +24,14 @@ import { Using } from '@azure-tools/codegen-csharp'; import { Local, LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { HttpOperation, Schema } from '../code-model'; -import { State, NewState } from '../generator'; -import { CallbackParameter, NewCallbackParameter, OperationBodyParameter, OperationParameter, NewOperationParameter, NewOperationBodyParameter } from '../operation/parameter'; +import { NewState } from '../generator'; +import { NewCallbackParameter, NewOperationParameter, NewOperationBodyParameter } from '../operation/parameter'; import { isMediaTypeJson, isMediaTypeXml, KnownMediaType, knownMediaType, normalizeMediaType, parseMediaType } from '@azure-tools/codemodel-v3'; import { ClassType, dotnet, System } from '@azure-tools/codegen-csharp'; import { Ternery } from '@azure-tools/codegen-csharp'; -function removeEncoding(pp: OperationParameter, paramName: string, kmt: KnownMediaType): string { - const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; - return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; -} function newRemoveEncoding(pp: NewOperationParameter, paramName: string, kmt: KnownMediaType): string { const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; @@ -79,217 +75,6 @@ export class EventListener { } -export class OperationMethod extends Method { - public methodParameters: Array; - public bodyParameter?: OperationBodyParameter; - public contextParameter!: Parameter; - public senderParameter!: Parameter; - public resourceUri!: Parameter; - public callbacks = new Array(); - - protected callName: string; - - constructor(protected parent: Class, public operation: HttpOperation, public viaIdentity: boolean, protected state: State, objectInitializer?: DeepPartial) { - super(viaIdentity ? `${operation.details.csharp.name}ViaIdentity` : operation.details.csharp.name, System.Threading.Tasks.Task()); - this.apply(objectInitializer); - this.async = Modifier.Async; - this.returnsDescription = `A that will be complete when handling of the response is completed.`; - const $this = this; - - this.callName = `${operation.details.csharp.name}_Call`; - this.push(Using('NoSynchronizationContext', '')); - - // add parameters - this.methodParameters = []; - - const identity = new Parameter('viaIdentity', System.String); - if (this.viaIdentity) { - this.addParameter(identity); - } - - for (let index = 0; index < length(this.operation.parameters); index++) { - const value = this.operation.parameters[index]; - - const p = new OperationParameter(this, value, this.state.path('parameters', index)); - - if (value.details.csharp.constantValue) { - const constTd = state.project.modelsNamespace.resolveTypeDeclaration(value.schema, true, state); - p.defaultInitializer = constTd.deserializeFromString(KnownMediaType.UriParameter, new StringExpression(`${value.details.csharp.constantValue}`), toExpression(constTd.defaultOfType)); - } - - // don't add path parameters when we're in identity mode - if (!this.viaIdentity || value.in !== ParameterLocation.Path) { - this.addParameter(p); - } else { - this.add(function* () { - yield ''; - }); - } - this.methodParameters.push(p); - } - - this.description = this.operation.details.csharp.description; - - // add body paramter if there should be one. - if (this.operation.requestBody) { - // this request does have a request body. - this.bodyParameter = new OperationBodyParameter(this, 'body', this.operation.requestBody.description || '', this.operation.requestBody.schema, this.operation.requestBody.required, this.state.path('requestBody'), { - mediaType: knownMediaType(this.operation.requestBody.contentType), - contentType: this.operation.requestBody.contentType - }); - this.addParameter(this.bodyParameter); - } - - for (const responses of values(this.operation.responses)) { - for (const response of values(responses)) { - const responseType = response.schema ? state.project.modelsNamespace.resolveTypeDeclaration(response.schema, true, state) : null; - const headerType = response.headerSchema ? state.project.modelsNamespace.resolveTypeDeclaration(response.headerSchema, true, state) : null; - - const newCallbackParameter = new CallbackParameter(response.details.csharp.name, responseType, headerType, this.state, { description: response.details.csharp.description }); - this.addParameter(newCallbackParameter); - this.callbacks.push(newCallbackParameter); - - } - } - - // add eventhandler parameter - this.contextParameter = this.addParameter(new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive events.` })); - - // add optional parameter for sender - this.senderParameter = this.addParameter(new Parameter('sender', ClientRuntime.ISendAsync, { description: `an instance of an ${ClientRuntime.ISendAsync} pipeline to use to make the request.` })); - - let rx = this.operation.path; - // For post API, Some URI may contain an action string .e.x '/start' at the end - // of the URI, for such cases, we will drop the action string if identityCorrection - // is set in the configuration - if (this.operation.method === 'post' && this.state.project.identityCorrection) { - const idx = rx.lastIndexOf('/'); - rx = rx.substr(0, idx); - } - - - let url = `${this.operation.baseUrl}${this.operation.path.startsWith('/') ? this.operation.path.substr(1) : this.operation.path}`; - - - const serverParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Uri); - - const headerParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Header); - const pathParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Path); - const queryParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Query); - const cookieParams = this.methodParameters.filter(each => each.param.in === ParameterLocation.Cookie); - - // replace any server params in the uri - for (const pp of serverParams) { - url = url.replace(`{${pp.param.name}}`, `" - + ${pp.name} - + "`); - } - - for (const pp of pathParams) { - rx = rx.replace(`{${pp.param.name}}`, `(?<${pp.param.name}>[^/]+)`); - - if (this.viaIdentity) { - url = url.replace(`{${pp.param.name}}`, `" - + ${pp.name} - + "`); - } else { - url = url.replace(`{${pp.param.name}}`, `" - + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} - + "`); - } - } - rx = `"^${rx}$"`; - url = url.replace(/\s*\+ ""/gm, ''); - - const bp = this.bodyParameter; - // add method implementation... - - this.add(function* () { - const eventListener = new EventListener($this.contextParameter, $this.state.project.emitSignals); - - yield EOL; - - if ($this.viaIdentity) { - yield '// verify that Identity format is an exact match for uri'; - yield EOL; - - const match = Local('_match', `${System.Text.RegularExpressions.Regex.new(rx).value}.Match(${identity.value})`); - yield match.declarationStatement; - yield If(`!${match}.Success`, `throw new global::System.Exception("Invalid identity for URI '${$this.operation.path}'");`); - yield EOL; - yield '// replace URI parameters with values from identity'; - for (const pp of pathParams) { - yield `var ${pp.name} = ${match.value}.Groups["${pp.param.name}"].Value;`; - } - } - - yield '// construct URL'; - const urlV = new LocalVariable('_url', dotnet.Var, { - initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( - "${url}" - ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${removeEncoding(pp, pp.param.name, KnownMediaType.QueryParameter)}`, ` - + "&"` - )} - ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) - }); - yield urlV.declarationStatement; - - yield EOL; - - yield eventListener.signal(ClientRuntime.Events.URLCreated, urlV.value); - yield EOL; - - yield '// generate request object '; - yield `var request = ${System.Net.Http.HttpRequestMessage.new(`${ClientRuntime.fullName}.Method.${$this.operation.method.capitalize()}, ${urlV.value}`)};`; - yield eventListener.signal(ClientRuntime.Events.RequestCreated, urlV.value); - yield EOL; - - if (length(headerParams) > 0) { - yield '// add headers parameters'; - for (const hp of headerParams) { - if (hp.param.name === 'Content-Length') { - // content length is set when the request body is set - continue; - } - yield hp.serializeToContainerMember(KnownMediaType.Header, new LocalVariable('request.Headers', dotnet.Var), hp.param.name, ClientRuntime.SerializationMode.None); - } - yield EOL; - } - yield eventListener.signal(ClientRuntime.Events.HeaderParametersAdded, urlV.value); - - if (bp) { - yield '// set body content'; - yield `request.Content = ${bp.serializeToContent(bp.mediaType, ClientRuntime.SerializationMode.None)};`; - yield `request.Content.Headers.ContentType = ${System.Net.Http.Headers.MediaTypeHeaderValue.Parse(bp.contentType)};`; - yield eventListener.signal(ClientRuntime.Events.BodyContentSet, urlV.value); - } - - yield '// make the call '; - }); - } - - emitCall(returnFromCall: boolean) { - - // storage will return from the call for download, etc. - if (returnFromCall) { - this.returnType = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); - } - - this.add(`await this.${this.callName}(request,${this.callbacks.joinWith(each => each.use, ',')},${this.contextParameter.use},${this.senderParameter.use});`); - - // remove constant parameters and make them locals instead. - this.insert('// Constant Parameters'); - for (let i = length(this.parameters); i--; i < 0) { - const p = this.parameters[i]; - if (p && p.defaultInitializer) { - this.parameters.splice(i, 1); - this.insert(new LocalVariable(p.name, dotnet.Var, { initializer: p.defaultInitializer })); - } - } - } -} - export class NewOperationMethod extends Method { public methodParameters: Array; public bodyParameter?: NewOperationBodyParameter; @@ -300,7 +85,7 @@ export class NewOperationMethod extends Method { protected callName: string; - constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: NewState, objectInitializer?: DeepPartial) { super(viaIdentity ? `${operation.language.csharp?.name}ViaIdentity` : operation.language.csharp?.name || '', System.Threading.Tasks.Task()); this.apply(objectInitializer); this.async = Modifier.Async; @@ -507,11 +292,11 @@ export class NewOperationMethod extends Method { } } } -export class CallMethod extends Method { +export class NewCallMethod extends Method { public returnNull = false; - constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { - super(`${opMethod.operation.details.csharp.name}_Call`, System.Threading.Tasks.Task()); - this.description = `Actual wire call for method.`; + constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); + this.description = `Actual wire call for method.`; this.returnsDescription = opMethod.returnsDescription; this.apply(objectInitializer); @@ -545,17 +330,18 @@ export class CallMethod extends Method { // add response handlers yield Switch(`${response}.StatusCode`, function* () { - for (const { key: responseCode, value: responses } of items(opMethod.operation.responses)) { - if (responseCode !== 'default') { + for (const responses of [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)]) { + if (responses.protocol.http?.statusCodes[0] !== 'default') { + const responseCode = responses.protocol.http?.statusCodes[0]; // will use enum when it can, fall back to casting int when it can't - yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.responsesEmitter($this, opMethod, responses, eventListener)); + yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); } else { - yield DefaultCase($this.responsesEmitter($this, opMethod, responses, eventListener)); + yield DefaultCase($this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); } } // missing default response? - if (!opMethod.operation.responses.default) { + if (!opMethod.operation.exceptions) { // if no default, we need one that handles the rest of the stuff. yield TerminalDefaultCase(function* () { yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`; @@ -571,13 +357,13 @@ export class CallMethod extends Method { yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value); const EOL = 'EOL'; // LRO processing (if appropriate) - if ($this.opMethod.operation.details.csharp.lro) { + if ($this.opMethod.operation.language.csharp?.lro) { yield '// this operation supports x-ms-long-running-operation'; const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`)); yield originalUri; - yield `// declared final-state-via: ${$this.opMethod.operation.details.csharp.lro['final-state-via']}`; - const fsv = $this.opMethod.operation.details.csharp.lro['final-state-via']; + yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`; + const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via']; let finalUri: LocalVariable; switch (fsv) { @@ -591,11 +377,10 @@ export class CallMethod extends Method { finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); yield finalUri; break; - case 'azure-asyncoperation': case 'azure-async-operation': - // depending on the type of request, do the appropriate behavior - switch ($this.opMethod.operation.method.toLowerCase()) { + //depending on the type of request, do the appropriate behavior + switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) { case 'post': case 'delete': finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); @@ -611,19 +396,20 @@ export class CallMethod extends Method { default: // depending on the type of request, fall back to the appropriate behavior - switch ($this.opMethod.operation.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; + if ($this.opMethod.operation.requests) { + switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) { + case 'post': + case 'delete': + finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); + yield finalUri; + break; + case 'patch': + case 'put': + // perform a final GET on the original URI. + finalUri = originalUri; + break; + } } - break; } @@ -782,12 +568,12 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield 'break;'; } - private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { + private * responsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { if (length(responses) > 1) { yield Switch('_contentType', function* () { for (const eachResponse of values(responses)) { const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); let count = length(eachResponse.mimeTypes); for (const mt of values(eachResponse.mimeTypes)) { @@ -805,15 +591,44 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) }); } else { const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); // all mimeTypes per for this response code. yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); } } + private * NewResponsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { + if (length(responses) > 1) { + yield Switch('_contentType', function* () { + for (const eachResponse of values(responses)) { + const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); + + let count = length(eachResponse.protocol.http?.mediaTypes); + for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { + count--; + const mediaType = normalizeMediaType(mt); + if (mediaType) { + if (count === 0) { + yield Case(new StringExpression(mediaType).toString(), $this.NewResponseHandler(mimetype, eachResponse, callbackParameter)); + } else { + yield TerminalCase(new StringExpression(mediaType).toString(), ''); + } + } + } + } + }); + } else { + const response = responses[0]; + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); + // all mimeTypes per for this response code. + yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); + yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); + } + } - private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { + private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: NewCallbackParameter) { const callbackParameters = new Array(); if (callbackParameter.responseType) { @@ -841,381 +656,13 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - public responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { - return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); - } -} -export class NewCallMethod extends Method { - public returnNull = false; - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { - super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); - this.description = `Actual wire call for method.`; - this.returnsDescription = opMethod.returnsDescription; + private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: NewCallbackParameter) { + const callbackParameters = new Array(); - this.apply(objectInitializer); - this.access = Access.Internal; - this.async = Modifier.Async; - this.push(Using('NoSynchronizationContext', '')); - - const $this = this; - // add parameters - // request, listener, sender - const reqParameter = this.addParameter(new Parameter('request', System.Net.Http.HttpRequestMessage, { description: 'the prepared HttpRequestMessage to send.' })); - opMethod.callbacks.forEach(each => this.addParameter(each)); - - this.addParameter(opMethod.contextParameter); - this.addParameter(opMethod.senderParameter); - - // add statements to this method - this.add(function* () { - const eventListener = new EventListener(opMethod.contextParameter, $this.state.project.emitSignals); - - const response = Local('_response', dotnet.Null, System.Net.Http.HttpResponseMessage); - yield response; - yield Try(function* () { - - const responder = function* () { - // TODO: omit generating _contentType var if it will never be used - // const contentType = new LocalVariable('_contentType', dotnet.Var, { initializer: `_response.Content.Headers.ContentType?.MediaType` }); - const contentType = Local('_contentType', `${response}.Content.Headers.ContentType?.MediaType`); - - yield contentType; - - // add response handlers - yield Switch(`${response}.StatusCode`, function* () { - for (const responses of [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)]) { - if (responses.protocol.http?.statusCodes[0] !== 'default') { - const responseCode = responses.protocol.http?.statusCodes[0]; - // will use enum when it can, fall back to casting int when it can't - yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); - } else { - yield DefaultCase($this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); - } - } - - // missing default response? - if (!opMethod.operation.exceptions) { - // if no default, we need one that handles the rest of the stuff. - yield TerminalDefaultCase(function* () { - yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`; - }); - } - }); - }; - - // try statements - yield eventListener.signal(ClientRuntime.Events.BeforeCall, reqParameter.use); - yield `${response.value} = await ${opMethod.senderParameter.value}.SendAsync(${reqParameter.use}, ${opMethod.contextParameter.value});`; - - yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value); - const EOL = 'EOL'; - // LRO processing (if appropriate) - if ($this.opMethod.operation.language.csharp?.lro) { - yield '// this operation supports x-ms-long-running-operation'; - const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`)); - yield originalUri; - - yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`; - const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via']; - let finalUri: LocalVariable; - - switch (fsv) { - case 'original-uri': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - - case 'location': - // perform a final GET on the uri in Location header - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'azure-asyncoperation': - case 'azure-async-operation': - //depending on the type of request, do the appropriate behavior - switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - } - break; - - default: - // depending on the type of request, fall back to the appropriate behavior - if ($this.opMethod.operation.requests) { - switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) { - case 'post': - case 'delete': - finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield finalUri; - break; - case 'patch': - case 'put': - // perform a final GET on the original URI. - finalUri = originalUri; - break; - } - } - break; - - } - - const asyncOperation = Local('asyncOperation', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield asyncOperation; - const location = Local('location', response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield location; - - yield While(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), function* () { - yield EOL; - yield '// get the delay before polling. (default to 30 seconds if not present)'; - yield `int delay = (int)(${response.value}.Headers.RetryAfter?.Delta?.TotalSeconds ?? 30);`; - // yield If(`!int.TryParse( ${response.invokeMethod('GetFirstHeader', new StringExpression(`Retry-After`)).value}, out int delay)`, `delay = 30;`); - - yield eventListener.signal(ClientRuntime.Events.DelayBeforePolling, '$"Delaying {delay} seconds before polling."', response.value); - - yield EOL; - yield '// start the delay timer (we\'ll await later...)'; - const waiting = Local('waiting', new LiteralExpression(`${System.Threading.Tasks.Task()}.Delay(delay * 1000, ${$this.opMethod.contextParameter}.Token )`)); - yield waiting; - - yield EOL; - yield '// while we wait, let\'s grab the headers and get ready to poll. '; - yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {'; - yield ' ' + asyncOperation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation'))); - yield '}'; - yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {'; - yield ' ' + location.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Location'))); - yield '}'; - const uriLocal = Local('_uri', Ternery( - System.String.IsNullOrEmpty(asyncOperation), - Ternery(System.String.IsNullOrEmpty(location), - originalUri, - location), - asyncOperation)); - yield uriLocal; - - yield `${reqParameter.use} = ${reqParameter.use}.CloneAndDispose(${System.Uri.new(uriLocal)}, ${ClientRuntime.Method.Get});`; - - yield EOL; - yield '// and let\'s look at the current response body and see if we have some information we can give back to the listener'; - const content = Local('content', new LiteralExpression(`await ${response.value}.Content.ReadAsStringAsync()`)); - yield content; - - yield 'await waiting;'; - - yield EOL; - yield '// check for cancellation'; - yield `if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; }`; - - yield eventListener.signal(ClientRuntime.Events.Polling, `$"Polling {${uriLocal}}."`, response.value); - - yield EOL; - yield '// drop the old response'; - yield `${response.value}?.Dispose();`; - - yield EOL; - yield '// make the polling call'; - yield `${response.value} = await ${opMethod.senderParameter}.SendAsync(${reqParameter.value}, ${opMethod.contextParameter});`; - - - yield EOL; - yield ` -// if we got back an OK, take a peek inside and see if it's done -if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) -{ - try { - if( ${ClientRuntime.JsonNode.Parse(toExpression(`await ${response.value}.Content.ReadAsStringAsync()`))} is ${ClientRuntime.JsonObject} json) - { - var state = json.Property("properties")?.PropertyT<${ClientRuntime.JsonString}>("provisioningState") ?? json.PropertyT<${ClientRuntime.JsonString}>("status"); - if( state is null ) - { - // the body doesn't contain any information that has the state of the LRO - // we're going to just get out, and let the consumer have the result - break; - } - await ${$this.opMethod.contextParameter}.Signal(${ClientRuntime.Events.Polling}, $"Polled {${uriLocal}} provisioning state {state}.", ${response.value}); if( ${$this.opMethod.contextParameter}.Token.IsCancellationRequested ) { return; } - - switch( state?.ToString()?.ToLower() ) - { - case "succeeded": - case "failed": - case "canceled": - // we're done polling. - break; - - default: - // need to keep polling! - ${response.value}.StatusCode = ${System.Net.HttpStatusCode.Created}; - continue; - } - } - } catch { - // if we run into a problem peeking into the result, - // we really don't want to do anything special. - } -}`; - - yield EOL; - yield '// check for terminal status code'; - yield If(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), 'continue;'); - - yield '// we are done polling, do a request on final target?'; - - switch (fsv) { - case 'original-uri': - case 'azure-asyncoperation': - case 'azure-async-operation': - case 'location': - // perform a final GET on the specified final URI. - yield $this.finalGet(finalUri, reqParameter, response); - break; - - default: - yield If(`!string.IsNullOrWhiteSpace(${finalUri})`, function* () { - yield $this.finalGet(finalUri, reqParameter, response); - }); - break; - } - }); - - } - yield responder(); - }); - - yield Finally(function* () { - yield '// finally statements'; - yield eventListener.signalNoCheck(ClientRuntime.Events.Finally, 'request', '_response'); - yield `${response.value}?.Dispose();`; - yield `${reqParameter.use}?.Dispose();`; - }); - - if ($this.returnNull) { - yield Return('result'); - $this.insert(new LocalVariable('result', System.Net.Http.HttpResponseMessage, { initializer: dotnet.Null })); - } - }); - - this.opMethod.emitCall($this.returnNull); - } - - private * finalGet(finalLocation: ExpressionOrLiteral, reqParameter: Variable, response: Variable) { - yield '// create a new request with the final uri'; - yield reqParameter.assign(`${valueOf(reqParameter)}.CloneAndDispose(${System.Uri.new(finalLocation)}, ${ClientRuntime.Method.Get})`); - - yield EOL; - yield '// drop the old response'; - yield `${response.value}?.Dispose();`; - - yield EOL; - yield '// make the final call'; - yield response.assign(`await ${this.opMethod.senderParameter}.SendAsync(${valueOf(reqParameter)}, ${this.opMethod.contextParameter})`); - - // make sure we're not polling anymore. - yield 'break;'; - } - - private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { - if (length(responses) > 1) { - yield Switch('_contentType', function* () { - for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); - - let count = length(eachResponse.mimeTypes); - for (const mt of values(eachResponse.mimeTypes)) { - count--; - const mediaType = normalizeMediaType(mt); - if (mediaType) { - if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.responseHandler(mimetype, eachResponse, callbackParameter)); - } else { - yield TerminalCase(new StringExpression(mediaType).toString(), ''); - } - } - } - } - }); - } else { - const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); - // all mimeTypes per for this response code. - yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); - } - } - - private * NewResponsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { - if (length(responses) > 1) { - yield Switch('_contentType', function* () { - for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); - - let count = length(eachResponse.protocol.http?.mediaTypes); - for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { - count--; - const mediaType = normalizeMediaType(mt); - if (mediaType) { - if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.NewResponseHandler(mimetype, eachResponse, callbackParameter)); - } else { - yield TerminalCase(new StringExpression(mediaType).toString(), ''); - } - } - } - } - }); - } else { - const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); - // all mimeTypes per for this response code. - yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); - } - } - - private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { - const callbackParameters = new Array(); - - if (callbackParameter.responseType) { - // hande the body response - const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); - if (r) { - - callbackParameters.push(r); - } - - // if (parseMediaType(mimetype)) { - // this media type isn't directly supported by deserialization - // we can return a stream to the consumer instead - // } - } - - if (callbackParameter.headerType) { - // header model deserialization... - const r = callbackParameter.headerType.deserializeFromResponse(KnownMediaType.Header, toExpression('_response'), toExpression('null')); - if (r) { - callbackParameters.push(r); - } - } - // make the callback with the appropriate parameters - yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; - } - - private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { - const callbackParameters = new Array(); - - if (callbackParameter.responseType) { - // hande the body response - const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); - if (r) { + if (callbackParameter.responseType) { + // hande the body response + const r = callbackParameter.responseType.deserializeFromResponse(knownMediaType(mimetype), toExpression('_response'), toExpression('null')); + if (r) { callbackParameters.push(r); } @@ -1237,58 +684,16 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.language.csharp?.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { + private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: NewCallbackParameter) { return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); } - private NewResponseHandler(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { + private NewResponseHandler(mimetype: string, eachResponse: Response, callbackParameter: NewCallbackParameter) { return this.NewResponseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); } } -export class ValidationMethod extends Method { - - constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { - super(`${opMethod.operation.details.csharp.name}_Validate`, System.Threading.Tasks.Task()); - this.apply(objectInitializer); - this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; - this.returnsDescription = opMethod.returnsDescription; - this.access = Access.Internal; - this.async = Modifier.Async; - this.push(Using('NoSynchronizationContext', '')); - - // add the method parameters - for (const parameter of opMethod.methodParameters) { - if (!parameter.defaultInitializer) { - this.addParameter(parameter); - } - } - - if (opMethod.bodyParameter) { - this.addParameter(opMethod.bodyParameter); - } - - this.addParameter(opMethod.contextParameter); - - // add statements to this method - this.add(function* () { - for (const parameter of opMethod.methodParameters) { - if (!parameter.defaultInitializer) { - // spit out parameter validation - yield parameter.validatePresenceStatement(opMethod.contextParameter); - yield parameter.validationStatement(opMethod.contextParameter); - } - } - - // spit out body parameter validation too - if (opMethod.bodyParameter) { - yield opMethod.bodyParameter.validatePresenceStatement(opMethod.contextParameter); - yield opMethod.bodyParameter.validationStatement(opMethod.contextParameter); - } - }); - } -} export class NewValidationMethod extends Method { - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { super(`${opMethod.name}_Validate`, System.Threading.Tasks.Task()); this.apply(objectInitializer); this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; diff --git a/powershell/llcsharp/operation/namespace.ts b/powershell/llcsharp/operation/namespace.ts index f2c8d1d854..c90f2d949a 100644 --- a/powershell/llcsharp/operation/namespace.ts +++ b/powershell/llcsharp/operation/namespace.ts @@ -6,12 +6,12 @@ import { ImportDirective } from '@azure-tools/codegen-csharp'; import { Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class ServiceNamespace extends Namespace { - constructor(public state: State | NewState, objectInitializer?: DeepPartial) { - super(state instanceof NewState ? state.model.language.csharp?.namespace : state.model.details.csharp.namespace || 'INVALID-NAMESPACE', state.project); + constructor(public state: NewState, objectInitializer?: DeepPartial) { + super(state.model.language.csharp?.namespace, state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); } diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index ea6f207eaa..546325a446 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -16,63 +16,17 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { HttpOperationParameter, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { State, NewState } from '../generator'; +import { NewState } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; /** represents a method parameter for an http operation (header/cookie/query/path) */ -export class OperationParameter extends Parameter implements EnhancedVariable { - public typeDeclaration: EnhancedTypeDeclaration; - - public param: HttpOperationParameter; - - constructor(parent: Method, param: HttpOperationParameter, state: State, objectInitializer?: DeepPartial) { - const typeDeclaration = state.project.modelsNamespace.resolveTypeDeclaration(param.schema, param.required, state.path('schema')); - super(param.details.csharp.name, typeDeclaration); - this.param = param; - this.typeDeclaration = typeDeclaration; - this.apply(objectInitializer); - this.description = param.details.csharp.description || ''; - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)) - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); - } - - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validatePresence(eventListener, this); - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validateValue(eventListener, this); - } -} export class NewOperationParameter extends Parameter implements EnhancedVariable { public typeDeclaration: NewEnhancedTypeDeclaration; public param: NewHttpOperationParameter; - constructor(parent: Method, param: NewHttpOperationParameter, state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Method, param: NewHttpOperationParameter, state: NewState, objectInitializer?: DeepPartial) { const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(param.schema, !!param.required, state); super(param.language.csharp?.name || '', typeDeclaration); this.param = param; @@ -115,65 +69,6 @@ export class NewOperationParameter extends Parameter implements EnhancedVariable } /** represents a method parameter for an http operation (body) */ -export class OperationBodyParameter extends Parameter implements EnhancedVariable { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { - // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)); - return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral): Expression { - // return this.assign(this.typeDeclaration.deserializeFromNode(mediaType, node, this)); - return this.typeDeclaration.deserializeFromNode(mediaType, node, this); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, serializedName: string, mode: Expression): Expression { - return this.typeDeclaration.serializeToNode(mediaType, this, serializedName, mode); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, mode: Expression): Expression { - return this.typeDeclaration.serializeToContent(mediaType, this, mode); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - return this.typeDeclaration.serializeToContainerMember(mediaType, this, container, serializedName, mode); - } - - public validatePresenceStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validatePresence(eventListener, this); - } - public validationStatement(eventListener: Variable): OneOrMoreStatements { - return this.typeDeclaration.validateValue(eventListener, this); - } - public mediaType: KnownMediaType; - public contentType: string; - - public typeDeclaration: EnhancedTypeDeclaration; - - constructor(parent: Method, name: string, description: string, schema: Schema, required: boolean, state: State, objectInitializer?: DeepPartial) { - const typeDeclaration = state.project.modelsNamespace.resolveTypeDeclaration(schema, required, state.path('schema')); - super(name, typeDeclaration); - this.typeDeclaration = typeDeclaration; - this.mediaType = KnownMediaType.Json; - this.contentType = KnownMediaType.Json; - - this.apply(objectInitializer); - this.description = description || schema.details.csharp.description; - } - - public get jsonSerializationStatement(): OneOrMoreStatements { - // get the body serialization from the typeDeclaration. - - return '/* body parameter */';// (this.type).jsonserialize(this.name); - } - public get jsonDeserializationStatement(): OneOrMoreStatements { - return '/* body parameter */';// (this.type).jsonDeserializationImplementation(this.name); - } -} export class NewOperationBodyParameter extends Parameter implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ @@ -235,41 +130,12 @@ export class NewOperationBodyParameter extends Parameter implements EnhancedVari } } -export class CallbackParameter extends Parameter { - responseType: (EnhancedTypeDeclaration) | null; - headerType: (EnhancedTypeDeclaration) | null; - - constructor(name: string, responseType: (EnhancedTypeDeclaration) | null, headerType: (EnhancedTypeDeclaration) | null, state: State, objectInitializer?: DeepPartial) { - // regular pipeline style. (callback happens after the pipline is called) - if (responseType) { - if (headerType) { - // both - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); - } else { - // just response - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(responseType), System.Threading.Tasks.Task())); - } - } else { - if (headerType) { - // just headers - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task(headerType), System.Threading.Tasks.Task())); - } else { - // no content? - super(name, System.Func(System.Net.Http.HttpResponseMessage, System.Threading.Tasks.Task())); - } - } - - this.responseType = responseType; - this.headerType = headerType; - this.apply(objectInitializer); - } -} export class NewCallbackParameter extends Parameter { responseType: (NewEnhancedTypeDeclaration) | null; headerType: (NewEnhancedTypeDeclaration) | null; - constructor(name: string, responseType: (NewEnhancedTypeDeclaration) | null, headerType: (NewEnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, responseType: (NewEnhancedTypeDeclaration) | null, headerType: (NewEnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { // regular pipeline style. (callback happens after the pipline is called) if (responseType) { if (headerType) { diff --git a/powershell/llcsharp/project.ts b/powershell/llcsharp/project.ts index e20ffe398b..20e7b6cff1 100644 --- a/powershell/llcsharp/project.ts +++ b/powershell/llcsharp/project.ts @@ -7,92 +7,13 @@ import { Host } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { State, NewState } from './generator'; -import { ModelsNamespace, NewModelsNamespace } from './model/namespace'; +import { NewState } from './generator'; +import { NewModelsNamespace } from './model/namespace'; import { ApiClass } from './operation/api-class'; import { ServiceNamespace } from './operation/namespace'; import { SupportNamespace } from './enums/namespace'; import { DeepPartial } from '@azure-tools/codegen'; - -export class Project extends codeDomProject { - - public jsonSerialization = true; - public xmlSerialization = false; - public defaultPipeline = true; - public emitSignals = true; - public projectNamespace!: string; - public overrides!: Dictionary; - protected state!: State; - - apifolder!: string; - runtimefolder!: string; - azure!: boolean; - license!: string; - identityCorrection!: boolean; - - constructor(protected service: Host, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - - public async init(): Promise { - await super.init(); - - this.state = await new State(this.service).init(this); - this.apifolder = await this.state.getValue('api-folder', ''); - this.runtimefolder = await this.state.getValue('runtime-folder', 'runtime'); - this.azure = await this.state.getValue('azure', false) || await this.state.getValue('azure-arm', false); - this.identityCorrection = await this.state.getValue('identity-correction-for-post', false); - this.license = await this.state.getValue('header-text', ''); - - - // add project namespace - this.projectNamespace = this.state.model.details.csharp.namespace; - this.overrides = { - 'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`, - 'Carbon.Data': `${this.projectNamespace}.Runtime.Json`, - 'using Converters;': '', - 'using Internal.Extensions;': '', - 'using Data;': '', - 'using Parser;': '', - - 'Carbon.Json': `${this.projectNamespace}.Runtime.Json`, - 'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`, - 'Microsoft.Rest': this.projectNamespace - }; - - this.serviceNamespace = new ServiceNamespace(this.state); - this.serviceNamespace.header = this.license; - this.addNamespace(this.serviceNamespace); - - // add support namespace - this.supportNamespace = new SupportNamespace(this.serviceNamespace, this.state); - this.supportNamespace.header = this.license; - this.addNamespace(this.supportNamespace); - - // add model classes - this.modelsNamespace = new ModelsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); - this.modelsNamespace.header = this.license; - this.addNamespace(this.modelsNamespace); - - // create API class - new ApiClass(this.serviceNamespace, this.state, { description: `Low-level API implementation for the ${this.state.model.info.title} service. \n${this.state.model.info.description || ''}` }); - - // abort now if we have any errors. - this.state.checkpoint(); - - return this; - } - - public serviceNamespace!: ServiceNamespace; - public modelsNamespace!: ModelsNamespace; - public supportNamespace!: SupportNamespace; -} - export class NewProject extends codeDomProject { public jsonSerialization = true; @@ -109,7 +30,7 @@ export class NewProject extends codeDomProject { license!: string; identityCorrection!: boolean; - constructor(protected service: Host, objectInitializer?: DeepPartial) { + constructor(protected service: Host, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index bd1eab1c70..0935d3487a 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -5,7 +5,7 @@ import { codeModelSchema, ArraySchema, UnixTimeSchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel'; -import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; +import { codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; import { ArrayOf, NewArrayOf } from './array'; @@ -23,136 +23,10 @@ import { String, NewString } from './string'; import { Uuid, NewUuid } from './Uuid'; import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; import { PwshModel } from '../../utils/PwshModel'; -import { NewModelState } from '../../utils/model-state'; +import { ModelState } from '../../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { schemaHasEnum } from '../validations'; -export class SchemaDefinitionResolver { - private readonly cache = new Map(); - private add(schema: Schema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { - this.cache.set(schema.details.csharp.fullname || '', value); - return value; - } - - resolveTypeDeclaration(schema: Schema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { - if (!schema) { - throw new Error('SCHEMA MISSING?'); - } - - // determine if we need a new model class for the type or just a known type object - switch (schema.type) { - case JsonType.Array: { - // can be recursive! - // handle boolean arrays as booleans (powershell will try to turn it into switches!) - const elementType = (schema.items && schema.items.type === JsonType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(schema.items, true, state.path('items')); - return new ArrayOf(schema, required, elementType, schema.minItems, schema.maxItems, schema.uniqueItems); - } - - case JsonType.Object: { - const result = schema.details.csharp && this.cache.get(schema.details.csharp.fullname || ''); - if (result) { - return result; - } - return this.add(schema, new ObjectImplementation(schema)); - } - case JsonType.String: - switch (schema.format) { - case StringFormat.Base64Url: - case StringFormat.Byte: - // member should be byte array - // on wire format should be base64url - return new ByteArray(schema, required); - - case StringFormat.Binary: - // represent as a stream - // wire format is stream of bytes - return new Binary(schema, required); - - case StringFormat.Char: - // a single character - return new Char(schema, required); - - case StringFormat.Date: - return new Date(schema, required); - - case StringFormat.DateTime: - return new DateTime(schema, required); - - case StringFormat.DateTimeRfc1123: - return new DateTime1123(schema, required); - - case StringFormat.Duration: - return new Duration(schema, required); - - case StringFormat.Uuid: - return new Uuid(schema, required); - - case StringFormat.Url: - case StringFormat.Password: - case StringFormat.None: - case undefined: - case null: - if (schema.extensions && schema.extensions['x-ms-enum']) { - return new EnumImplementation(schema, required); - } - /* - if(schema.extensions && schema.extensions['x-ms-header-collection-prefix']) { - return new Wildcard(schema, new String({}, required)); - } - */ - // just a regular old string. - return new String(schema, required); - - default: - state.warning(`Schema with type:'${schema.type} and 'format:'${schema.format}' is not recognized.`, message.DoesNotSupportEnum); - return new String(schema, required); - } - - case JsonType.Boolean: - return new Boolean(schema, required); - - case JsonType.Integer: - switch (schema.format) { - case IntegerFormat.Int64: - case IntegerFormat.None: - return new Numeric(schema, required, required ? 'long' : 'long?'); - case IntegerFormat.UnixTime: - return new UnixTime(schema, required); - case IntegerFormat.Int32: - return new Numeric(schema, required, required ? 'int' : 'int?'); - } - // fallback to int if the format isn't recognized - return new Numeric(schema, required, required ? 'int' : 'int?'); - - case JsonType.Number: - switch (schema.format) { - case NumberFormat.None: - case NumberFormat.Double: - return new Numeric(schema, required, required ? 'double' : 'double?'); - case NumberFormat.Float: - return new Numeric(schema, required, required ? 'float' : 'float?'); - case NumberFormat.Decimal: - return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); - } - // fallback to float if the format isn't recognized - return new Numeric(schema, required, required ? 'float' : 'float?'); - - case undefined: - if (schema.extensions && schema.extensions['x-ms-enum']) { - return new EnumImplementation(schema, required); - } - - // "any" case - // this can happen when a model is just an all-of something else. (sub in the other type?) - break; - - } - state.error(`Schema '${schema.details.csharp.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType); - throw new Error('Unknown Model. Fatal.'); - } - -} - export class NewSchemaDefinitionResolver { private readonly cache = new Map(); private add(schema: NewSchema, value: NewEnhancedTypeDeclaration): NewEnhancedTypeDeclaration { @@ -160,7 +34,7 @@ export class NewSchemaDefinitionResolver { return value; } - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): NewEnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } diff --git a/powershell/llcsharp/validations.ts b/powershell/llcsharp/validations.ts index 0a86cb8934..9300bce754 100644 --- a/powershell/llcsharp/validations.ts +++ b/powershell/llcsharp/validations.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { JsonType, Schema } from '@azure-tools/codemodel-v3'; -import { State } from './generator'; +import { NewState } from './generator'; import * as message from './messages'; import { length } from '@azure-tools/linq'; -export function objectWithFormat(schema: Schema, state: State): boolean { +export function objectWithFormat(schema: Schema, state: NewState): boolean { if (schema.type === JsonType.Object && schema.format) { state.error(`Schema is declared 'object' but has a format: '${schema.format}'`, message.ObjectShouldNotHaveFormat); return true; @@ -16,7 +16,7 @@ export function objectWithFormat(schema: Schema, state: State): boolean { return false; } -export function schemaHasEnum(schema: Schema, state: State): boolean { +export function schemaHasEnum(schema: Schema, state: NewState): boolean { if (length(schema.enum) > 0) { state.error(`Schema with type:'${schema.type} and 'format:'${schema.format}' does not support 'enum' value restrictions.`, message.DoesNotSupportEnum); return true; @@ -24,7 +24,7 @@ export function schemaHasEnum(schema: Schema, state: State): boolean { return false; } -export function hasXmsEnum(schema: Schema, state: State): boolean { +export function hasXmsEnum(schema: Schema, state: NewState): boolean { if (length(schema.enum) > 0) { if (schema.extensions && schema.extensions['x-ms-enum']) { state.error(`Schema with type:'${schema.type} and 'format:'${schema.format}' does not support 'x-ms-enum' generation `, message.SchemaDoeNotSupportXMSEnum); @@ -34,7 +34,7 @@ export function hasXmsEnum(schema: Schema, state: State): boolean { return false; } -export function arrayMissingItems(schema: Schema, state: State): boolean { +export function arrayMissingItems(schema: Schema, state: NewState): boolean { if (schema.type === JsonType.Array && !schema.items) { state.error('Array schema missing items type', message.ArrayMissingItems); return true; diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 2f0e682375..9fbd4c337d 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -5,8 +5,8 @@ import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; -import { Schema, ClientRuntime, SchemaDefinitionResolver, ObjectImplementation, NewObjectImplementation, DeserializerPartialClass, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; +import { Schema, ClientRuntime, ObjectImplementation, NewObjectImplementation, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; +import { NewState } from '../internal/state'; import { PSObject, PSTypeConverter, TypeConverterAttribute } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -16,245 +16,13 @@ class ApiVersionModelExtensionsNamespace extends Namespace { public get outputFolder(): string { return `${this.baseFolder}/${this.apiVersion.replace(/.*\./g, '')}`; } - constructor(private baseFolder: string, private readonly apiVersion: string, objectInitializer?: DeepPartial) { + constructor(private baseFolder: string, private readonly apiVersion: string, objectInitializer?: DeepPartial) { super(apiVersion); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); } } -export class ModelExtensionsNamespace extends Namespace { - CreateReferenceType(): Class { - const rt = new Class(this, 'ReferenceType'); - rt.add(new Property('Id', dotnet.String, { setAccess: Access.Internal })); - return rt; - } - private subNamespaces = new Dictionary(); - - public get outputFolder(): string { - return join(this.state.project.apiFolder, 'Models'); - } - resolver = new SchemaDefinitionResolver(); - - constructor(parent: Namespace, private schemas: Dictionary, private state: State, objectInitializer?: DeepPartial) { - super('Models', parent); - this.apply(objectInitializer); - this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); - this.subNamespaces[this.fullName] = this; - - const $this = this; - const resolver = (s: Schema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state); - - // Add typeconverters to model classes (partial) - for (const schema of values(schemas)) { - if (!schema || schema.details.csharp.skip) { - continue; - } - - const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof ObjectImplementation) { - - // it's a class object. - const className = td.schema.details.csharp.name; - const interfaceName = td.schema.details.csharp.interfaceName || ''; - const converterClass = `${className}TypeConverter`; - - if (this.findClassByName(className).length > 0) { - continue; - } - - // get the actual full namespace for the schema - const fullname = schema.details.csharp.namespace || this.fullName; - const ns = this.subNamespaces[fullname] || this.add(new ApiVersionModelExtensionsNamespace(this.outputFolder, fullname)); - - // create the model extensions for each object model - // 2. A partial interface with the type converter attribute - const modelInterface = new Interface(ns, interfaceName, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. - }); - modelInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - - // 1. A partial class with the type converter attribute - const model = new Class(ns, className, undefined, { - partial: true, - description: td.schema.details.csharp.description, - fileName: `${className}.PowerShell` - }); - - // if the model is supposed to be use 'by-reference' we should create an I*Reference interface for that - // and add that interface to the extension class - if (schema.details.csharp.byReference) { - const refInterface = `${interfaceName}_Reference`; - schema.details.csharp.referenceInterface = `${ns.fullName}.${refInterface}`; - - const referenceInterface = new Interface(ns, refInterface, { - partial: true, - description: `Reference for model ${fullname}`, - fileName: `${interfaceName}.PowerShell` // make sure that the interface ends up in the same file as the class. - }); - referenceInterface.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - referenceInterface.add(new InterfaceProperty('Id', dotnet.String, { setAccess: Access.Internal })); - model.interfaces.push(referenceInterface); - - // add it to the generic reference type. - // referenceType = referenceType || this.CreateReferenceType(); - // referenceType.interfaces.push(referenceInterface); - } - - - model.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] })); - model.add(new LambdaMethod('FromJsonString', modelInterface, new LiteralExpression(`FromJson(${ClientRuntime.JsonNode.declaration}.Parse(jsonText))`), { - static: Modifier.Static, - parameters: [new Parameter('jsonText', dotnet.String, { description: 'a string containing a JSON serialized instance of this model.' })], - description: `Creates a new instance of , deserializing the content from a json string.`, - returnsDescription: 'an instance of the model class.' - })); - - model.add(new LambdaMethod('ToJsonString', dotnet.String, new LiteralExpression(`ToJson(${dotnet.Null}, ${ClientRuntime.SerializationMode.IncludeAll})?.ToString()`), { - description: 'Serializes this instance to a json string.', - returnsDescription: 'a containing this model serialized to JSON text.' - })); - - const hashDeseralizer = new DeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); - const psDeseralizer = new DeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); - - // + static FromJsonString(string json); - // + string ToJsonString() - - // 3. A TypeConverter class - const typeConverter = new Class(ns, converterClass, PSTypeConverter, { - description: `A PowerShell PSTypeConverter to support converting to an instance of `, - fileName: `${className}.TypeConverter` - }); - typeConverter.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the parameter can be converted to the parameter', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false', - })); - typeConverter.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], description: 'NotImplemented -- this will return null', - returnsDescription: 'will always return null.' - })); - typeConverter.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, new LiteralExpression('CanConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }) - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: 'true if the converter can convert the parameter to the parameter, otherwise false.', - })); - typeConverter.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression('ConvertFrom(sourceValue)'), { - override: Modifier.Override, - parameters: [ - new Parameter('sourceValue', dotnet.Object, { description: 'the to convert from' }), - new Parameter('destinationType', System.Type, { description: 'the to convert to' }), - new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }), - new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to true, will ignore the case when converting.' }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })); - - typeConverter.add(new Method('CanConvertFrom', dotnet.Bool, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { description: `the instance to check if it can be converted to the type.` }), - ], - description: 'Determines if the converter can convert the parameter to the parameter.', - returnsDescription: `true if the instance could be converted to a type, otherwise false ` - })).add(function* () { - yield If('null == sourceValue', Return(dotnet.True)); - - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; - - if (schema.details.default.uid === 'universal-parameter-type' || schema.details.csharp.byReference) { - yield '// we allow string conversion too.'; - yield If(`${t.value} == typeof(${System.String})`, Return(dotnet.True)); - } - - yield If(IsAssignableFrom(PSObject, t), function* () { - yield '// we say yest to PSObjects'; - yield Return(dotnet.True); - }); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), function* () { - yield '// we say yest to Hashtables/dictionaries'; - yield Return(dotnet.True); - }); - - yield Try(If('null != sourceValue.ToJsonString()', Return(dotnet.True))); - yield Catch(undefined, '// Not one of our objects'); - - yield Try(function* () { - const t = new LocalVariable('text', dotnet.String, { initializer: 'sourceValue.ToString()?.Trim()' }); - yield t.declarationStatement; - yield Return(`${dotnet.True} == ${t.value}?.StartsWith("{") && ${dotnet.True} == ${t.value}?.EndsWith("}") && ${ClientRuntime.JsonNode.Parse(t)}.Type == ${ClientRuntime.JsonType.Object}`); - }); - yield Catch(undefined, '// Doesn\'t look like it can be treated as JSON'); - - yield Return(dotnet.False); - }); - - typeConverter.add(new Method('ConvertFrom', modelInterface, { - static: Modifier.Static, - parameters: [ - new Parameter('sourceValue', dotnet.Dynamic, { - description: `the value to convert into an instance of .` - }), - ], - description: 'Converts the parameter to the parameter using and ', - returnsDescription: `an instance of , or null if there is no suitable conversion.` - })).add(function* () { - // null begets null - yield If('null == sourceValue', Return(dotnet.Null)); - - const t = new LocalVariable('type', System.Type, { initializer: 'sourceValue.GetType()' }); - yield t.declarationStatement; - - if (($this.state.project.azure && schema.details.default.uid === 'universal-parameter-type') || schema.details.csharp.byReference) { - yield '// support direct string to id type conversion.'; - yield If(`${t.value} == typeof(${System.String})`, function* () { - yield Return(`new ${className} { Id = sourceValue }`); - }); - } - - if (schema.details.csharp.byReference) { - yield '// if Id is present with by-reference schemas, just return the type with Id '; - yield Try(Return(`new ${className} { Id = sourceValue.Id }`)); - yield Catch(undefined, '// Not an Id reference parameter'); - } - - // if the type can be assigned directly, do that - yield If(IsAssignableFrom(td, t), Return('sourceValue')); - - // try using json first (either from string or toJsonString()) - yield Try(Return(`${className}.FromJsonString(typeof(string) == sourceValue.GetType() ? sourceValue : sourceValue.ToJsonString());`)); - yield Catch(undefined, '// Unable to use JSON pattern'); - - yield If(IsAssignableFrom(PSObject, t), Return(`${className}.DeserializeFromPSObject(sourceValue)`)); - yield If(IsAssignableFrom(System.Collections.IDictionary, t), Return(`${className}.DeserializeFromDictionary(sourceValue)`)); - - // null if not successful - yield Return(dotnet.Null); - }); - } - } - } -} - export class NewModelExtensionsNamespace extends Namespace { CreateReferenceType(): Class { const rt = new Class(this, 'ReferenceType'); @@ -268,7 +36,7 @@ export class NewModelExtensionsNamespace extends Namespace { } resolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary>, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private schemas: Dictionary>, private state: NewState, objectInitializer?: DeepPartial) { super('Models', parent); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index 58b8193382..b7883aae6d 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -6,291 +6,10 @@ import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, If, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; import { InvocationInfo, PSCredential, IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, } from '../internal/powershell-declarations'; -import { State, NewState } from '../internal/state'; +import { NewState } from '../internal/state'; import { ClientRuntime } from '../llcsharp/exports'; import { DeepPartial } from '@azure-tools/codegen'; -export class ModuleClass extends Class { - - // get the name of the client API class - TaskOfHttpResponseMessage = System.Threading.Tasks.Task(System.Net.Http.HttpResponseMessage); - - // lets the common code call the signal again (recursive! careful!) - incomingSignalFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - /* returns */ System.Threading.Tasks.Task()); - - eventListenerFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - this.incomingSignalFunc, - InvocationInfo, - dotnet.String, - dotnet.String, - dotnet.String, - System.Exception, - /* returns */ System.Threading.Tasks.Task()); - - IEventListenerExpanded = [ - System.Threading.CancellationToken, /* token */ - System.Action(), /* Cancel() */ - this.incomingSignalFunc, - ]; - - nextStep = System.Func( - System.Net.Http.HttpRequestMessage, - ...this.IEventListenerExpanded, - /* returns */ this.TaskOfHttpResponseMessage); - - initMethod = this.add(new Method('Init', dotnet.Void, { description: 'Initialization steps performed after the module is loaded.' })); - createPipelineMethod!: Method; - - pInvocationInfo = new Parameter('invocationInfo', InvocationInfo, { description: 'The from the cmdlet' }); - pPipeline = new Parameter('pipeline', ClientRuntime.HttpPipeline, { modifier: ParameterModifier.Ref, description: 'The HttpPipeline for the request' }); - pProxy = new Parameter('proxy', System.Uri, { description: 'The HTTP Proxy to use.' }); - pProxyCredential = new Parameter('proxyCredential', PSCredential, { description: 'The HTTP Proxy Credentials' }); - pUseDefaultCredentials = new Parameter('proxyUseDefaultCredentials', dotnet.Bool, { description: 'True if the proxy should use default credentials' }); - - pCorrelationId = new Parameter('correlationId', dotnet.String, { description: 'the cmdlet\'s correlation id.' }); - pParameterName = new Parameter('parameterName', dotnet.String, { description: 'The name of the parameter to get the value for.' }); - - pId = new Parameter('id', dotnet.String, { description: 'The ID of the event ' }); - pToken = new Parameter('token', System.Threading.CancellationToken, { description: 'The cancellation token for the event ' }); - pGetEventData = new Parameter('getEventData', System.Func(System.EventArgs), { description: 'A delegate to get the detailed event data' }); - - pParameterSetName = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.' }); - pParameterSetNameWithDefault = new Parameter('parameterSetName', dotnet.String, { description: 'the cmdlet\'s parameterset name.', defaultInitializer: dotnet.Null }); - pProcessRecordId = new Parameter('processRecordId', dotnet.String, { description: 'the cmdlet\'s process record correlation id.' }); - pException = new Parameter('exception', System.Exception, { description: 'the exception that is being thrown (if available)' }); - - fPipeline = this.add(new Field('_pipeline', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance' })); - fPipelineWithProxy = this.add(new Field('_pipelineWithProxy', ClientRuntime.HttpPipeline, { access: Access.Private, description: 'the ISendAsync pipeline instance (when proxy is enabled)' })); - fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); - fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); - - constructor(namespace: Namespace, private readonly state: State, objectInitializer?: DeepPartial) { - super(namespace, 'Module'); - this.apply(objectInitializer); - this.partial = true; - this.description = 'A class that contains the module-common code and data.'; - - const $this = this; - - // static instance property - this.add(new LazyProperty('Instance', this, new LiteralExpression(`new ${this.declaration}()`), { - instanceAccess: this.declaration, - static: Modifier.Static, - description: 'the singleton of this module class' - })); - - const clientAPI = new ClassType(this.state.model.details.csharp.namespace, this.state.model.details.csharp.name); - const clientProperty = this.add(new Property('ClientAPI', clientAPI, { description: 'The instance of the Client API' })); - - if (this.state.project.azure) { - this.createAzureInitAndPipeline(namespace); - } else { - this.createInitAndPipeline(namespace); - } - - this.add(new Constructor(this, { - access: Access.Private, - description: 'Creates the module instance.', - body: function* () { - yield '/// constructor'; - yield clientProperty.assignPrivate(clientAPI.new()); - yield `${$this.fHandler}.Proxy = ${$this.fWebProxy};`; - - yield $this.fPipeline.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new()))); - yield $this.fPipelineWithProxy.assignPrivate(ClientRuntime.HttpPipeline.new(ClientRuntime.HttpClientFactory.new(System.Net.Http.HttpClient.new($this.fHandler)))); - } - })); - - /* extensibility points */ - this.add(new PartialMethod('BeforeCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); - this.add(new PartialMethod('AfterCreatePipeline', dotnet.Void, { parameters: [this.pInvocationInfo, this.pPipeline] })); - this.add(new PartialMethod('CustomInit', dotnet.Void)); - - /* Setting the Proxy */ - this.add(new Method('SetProxyConfiguration', dotnet.Void, { - parameters: [this.pProxy, this.pProxyCredential, this.pUseDefaultCredentials], - *body() { - yield '// set the proxy configuration'; - yield `${$this.fWebProxy}.Address = proxy;`; - yield `${$this.fWebProxy}.BypassProxyOnLocal = false;`; - yield `${$this.fWebProxy}.Credentials = proxyCredential ?.GetNetworkCredential();`; - yield `${$this.fWebProxy}.UseDefaultCredentials = proxyUseDefaultCredentials;`; - yield `${$this.fHandler}.UseProxy = proxy != null;`; - } - })); - } - - createInitAndPipeline(namespace: Namespace) { - const $this = this; - // Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId) - const customEventListenerFunc = System.Func( - dotnet.String, - System.Threading.CancellationToken, - System.Func(System.EventArgs), - this.incomingSignalFunc, - InvocationInfo, - dotnet.String, - System.Exception, - /* returns */ System.Threading.Tasks.Task()); - - const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); - const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc)); - const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); - - // non-azure init method - this.initMethod.add(function* () { - yield '// called at module init time...'; - yield 'CustomInit();'; - }); - - this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { - parameters: [this.pInvocationInfo, this.pParameterSetNameWithDefault], - description: 'Creates an instance of the HttpPipeline for each call.', - returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` - })); - - // non-azure createPipeline method - this.createPipelineMethod.add(function* () { - const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); - yield pip.declarationStatement; - yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); - yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield Return(pip); - }); - - this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); - - // Add Signal extensibility point - const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); - // Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module - const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { - parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async, - description: 'Called to dispatch events to the common module listener', - returnsDescription: `A that will be complete when handling of the event is completed.` - })); - - signalImpl.push(Using('NoSynchronizationContext', '')); - signalImpl.add(function* () { - // Emit call to EventListener after explicit null check. - // Not using Null-Conditional operator causes Null Reference exception when Func is null, due to awaiting null Task. - yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`) - }); - } - - createAzureInitAndPipeline(namespace: Namespace) { - const $this = this; - - const sendAsyncStep = namespace.add(new Alias('SendAsyncStepDelegate', - System.Func( - System.Net.Http.HttpRequestMessage, - ...this.IEventListenerExpanded, - this.nextStep, /* Next( ...) */ - /* returns */ this.TaskOfHttpResponseMessage))); - - const pipelineChangeDelegate = namespace.add(new Alias('PipelineChangeDelegate', System.Action(sendAsyncStep.fullDefinition))); - - const getParameterDelegate = namespace.add(new Alias('GetParameterDelegate', System.Func( - dotnet.String, /* resourceId */ - dotnet.String, /* moduleName */ - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.String, /* parameterName */ - /* returns */ dotnet.Object))); - - const moduleLoadPipelineDelegate = namespace.add(new Alias('ModuleLoadPipelineDelegate', System.Action( - dotnet.String, /* resourceId */ - dotnet.String, /* moduleName */ - pipelineChangeDelegate.fullDefinition, /* prependStep */ - pipelineChangeDelegate.fullDefinition))); /* appendStep */ - - const newRequestPipelineDelegate = namespace.add(new Alias('NewRequestPipelineDelegate', System.Action( - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.String, /* processRecordId */ - pipelineChangeDelegate.fullDefinition, /* prependStep */ - pipelineChangeDelegate.fullDefinition))); /* appendStep */ - - const argumentCompleterDelegate = namespace.add(new Alias('ArgumentCompleterDelegate', System.Func( - dotnet.String, /* completerName */ - InvocationInfo, /* invocationInfo */ - dotnet.String, /* correlationId */ - dotnet.StringArray, /* resourceTypes */ - dotnet.StringArray, /* parentResourceParameterNames */ - /* returns */ dotnet.StringArray, - ))); - - const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc)); - const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', this.eventListenerFunc)); - - namespace.add(new Alias('NextDelegate', this.nextStep)); - - /* AzAccounts VTable properties */ - const OnModuleLoad = this.add(new Property('OnModuleLoad', moduleLoadPipelineDelegate, { description: 'The delegate to call when this module is loaded (supporting a commmon module).' })); - const OnNewRequest = this.add(new Property('OnNewRequest', newRequestPipelineDelegate, { description: 'The delegate to call before each new request (supporting a commmon module).' })); - const GetParameterValue = this.add(new Property('GetParameterValue', getParameterDelegate, { description: 'The delegate to call to get parameter data from a common module.' })); - const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' })); - const ArgumentCompleter = this.add(new Property('ArgumentCompleter', argumentCompleterDelegate, { description: 'Gets completion data for azure specific fields' })); - const ProfileName = this.add(new Property('ProfileName', System.String, { description: 'The name of the currently selected Azure profile' })); - - const moduleIdentity = this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' })); - const currentProfile = this.add(new Field('Profile', dotnet.String, { initialValue: System.String.Empty, description: 'The currently selected profile.' })); - const moduleResourceId = this.add(new LambdaProperty('ResourceId', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The ResourceID for this module (azure arm).' })); - - /* get parameter method (calls azAccounts) */ - this.add(new LambdaMethod('GetParameter', dotnet.Object, new LiteralExpression(`${GetParameterValue.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value}, ${$this.pInvocationInfo.value}, ${$this.pCorrelationId.value},${$this.pParameterName.value} )`), { - parameters: [this.pInvocationInfo, this.pCorrelationId, this.pParameterName], - description: 'Gets parameters from a common module.', - returnsDescription: 'The parameter value from the common module. (Note: this should be type converted on the way back)' - })); - - /* signal method (calls azAccounts) */ - const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' }); - const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), { - parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pCorrelationId, this.pProcessRecordId, this.pException], async: Modifier.Async, - description: 'Called to dispatch events to the common module listener', - returnsDescription: `A that will be complete when handling of the event is completed.` - })); - - signalImpl.push(Using('NoSynchronizationContext', '')); - signalImpl.add(function* () { - yield `await ${EventListener.value}?.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName}, ${$this.pCorrelationId},${$this.pProcessRecordId},${$this.pException});`; - }); - - /* init method */ - this.initMethod.add(function* () { - yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipeline.value}.Prepend(step); } , (step)=> { ${$this.fPipeline.value}.Append(step); } );`; - yield `${OnModuleLoad.value}?.Invoke( ${moduleResourceId.value}, ${moduleIdentity.value} ,(step)=> { ${$this.fPipelineWithProxy.value}.Prepend(step); } , (step)=> { ${$this.fPipelineWithProxy.value}.Append(step); } );`; - yield 'CustomInit();'; - }); - - this.createPipelineMethod = this.add(new Method('CreatePipeline', ClientRuntime.HttpPipeline, { - parameters: [this.pInvocationInfo, this.pCorrelationId, this.pProcessRecordId, this.pParameterSetNameWithDefault], - description: 'Creates an instance of the HttpPipeline for each call.', - returnsDescription: `An instance of ${ClientRuntime.HttpPipeline} for the remote call.` - })); - - /* pipeline create method */ - this.createPipelineMethod.add(function* () { - const pip = new LocalVariable('pipeline', ClientRuntime.HttpPipeline, { initializer: 'null' }); - yield pip.declarationStatement; - yield `BeforeCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield pip.assign(`(${pip} ?? (${$this.fHandler}.UseProxy ? ${$this.fPipelineWithProxy} : ${$this.fPipeline})).Clone()`); - yield `AfterCreatePipeline(${$this.pInvocationInfo.use}, ref ${pip});`; - yield `pipeline.Append(new Runtime.CmdInfoHandler(${$this.pProcessRecordId}, ${$this.pInvocationInfo.use}, ${$this.pParameterSetName}).SendAsync);`; - yield `${OnNewRequest.value}?.Invoke( ${$this.pInvocationInfo.use}, ${$this.pCorrelationId},${$this.pProcessRecordId}, (step)=> { ${pip}.Prepend(step); } , (step)=> { ${pip}.Append(step); } );`; - yield Return(pip); - }); - } -} - export class NewModuleClass extends Class { // get the name of the client API class @@ -352,7 +71,7 @@ export class NewModuleClass extends Class { fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); - constructor(namespace: Namespace, private readonly state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, private readonly state: NewState, objectInitializer?: DeepPartial) { super(namespace, 'Module'); this.apply(objectInitializer); this.partial = true; diff --git a/powershell/module/module-namespace.ts b/powershell/module/module-namespace.ts index 6913ba6936..7a566dac6d 100644 --- a/powershell/module/module-namespace.ts +++ b/powershell/module/module-namespace.ts @@ -4,27 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../llcsharp/exports'; -import { State, NewState } from '../internal/state'; -import { ModuleClass, NewModuleClass } from './module-class'; +import { NewState } from '../internal/state'; +import { NewModuleClass } from './module-class'; import { DeepPartial } from '@azure-tools/codegen'; -export class ModuleNamespace extends Namespace { - public moduleClass: ModuleClass; - - public get outputFolder(): string { - return this.state.project.moduleFolder; - } - - constructor(public state: State, objectInitializer?: DeepPartial) { - super(state.model.details.csharp.namespace || 'INVALID.NAMESPACE', state.project); - this.apply(objectInitializer); - this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); - - // module class - this.moduleClass = new ModuleClass(this, state); - } -} - export class NewModuleNamespace extends Namespace { public moduleClass: NewModuleClass; @@ -32,7 +15,7 @@ export class NewModuleNamespace extends Namespace { return this.state.project.moduleFolder; } - constructor(public state: NewState, objectInitializer?: DeepPartial) { + constructor(public state: NewState, objectInitializer?: DeepPartial) { super(state.model.language.csharp?.namespace || 'INVALID.NAMESPACE', state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); diff --git a/powershell/plugins/add-azure-completers-v2.ts b/powershell/plugins/add-azure-completers-v2.ts index 81b1ac87af..557ce43263 100644 --- a/powershell/plugins/add-azure-completers-v2.ts +++ b/powershell/plugins/add-azure-completers-v2.ts @@ -6,10 +6,10 @@ import { values } from '@azure-tools/linq'; import { Host } from '@azure-tools/autorest-extension-base'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { serialize } from '@azure-tools/codegen'; -type State = NewModelState; +type State = ModelState; const resourceGroupNames = new Set([ 'resourcegroupname', @@ -45,6 +45,6 @@ async function tweakModel(state: State): Promise { export async function addCompleterV2(service: Host) { - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-add-azure-completers-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/create-commands-v2.ts b/powershell/plugins/create-commands-v2.ts index d53d8132d1..fc36205364 100644 --- a/powershell/plugins/create-commands-v2.ts +++ b/powershell/plugins/create-commands-v2.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { HttpMethod, codeModelSchema, CodeModel, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -//import { JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, ModelState, ParameterLocation, } from '@azure-tools/codemodel-v3'; import { deconstruct, fixLeadingNumber, pascalCase, EnglishPluralizationService, fail, removeSequentialDuplicates, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Schema } from '../llcsharp/exports'; @@ -14,11 +13,11 @@ import { clone } from '@azure-tools/linq'; import { verbs } from '../internal/verbs'; import { PwshModel } from '../utils/PwshModel'; import { IParameter } from '../utils/components'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; //import { Schema as SchemaV3 } from '../utils/schema'; import { CommandOperation } from '../utils/command-operation'; -type State = NewModelState; +type State = ModelState; // UNUSED: Moved to plugin-tweak-model.ts in remodeler @@ -478,7 +477,7 @@ export async function createCommandsV2(service: Host) { // return processCodeModel(commandCreator, service); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-createcommands-v2.yaml', serialize(await (await new Inferrer(state).init()).createCommands()), undefined, 'code-model-v4'); // return processCodeModel(async (state) => { diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index 3443cd53c7..dea8d9e06f 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -4,19 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, StringSchema, ChoiceSchema, SealedChoiceSchema } from '@azure-tools/codemodel'; -//import { codemodel, JsonType, ModelState, processCodeModel, VirtualProperty } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { System } from '@azure-tools/codegen-csharp'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { SchemaDetails } from '../llcsharp/code-model'; -import { SchemaDefinitionResolver, NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; +import { NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { SchemaDetails as NewSchemaDetails } from '../utils/schema'; -type State = NewModelState; +type State = ModelState; function setPropertyNames(schema: Schema) { @@ -260,7 +259,7 @@ export async function csnamerV2(service: Host) { //return processCodeModel(nameStuffRight, service, 'csnamer'); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-csnamer-v2.yaml', serialize(await nameStuffRight(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/llcsharp-v2.ts b/powershell/plugins/llcsharp-v2.ts index a5c14fed49..115f267f8c 100644 --- a/powershell/plugins/llcsharp-v2.ts +++ b/powershell/plugins/llcsharp-v2.ts @@ -7,8 +7,7 @@ import { codeModelSchema } from '@azure-tools/codemodel'; import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; import { join } from 'path'; import { Model } from '../llcsharp/code-model'; -import { State } from '../llcsharp/generator'; -import { Project, NewProject } from '../llcsharp/project'; +import { NewProject } from '../llcsharp/project'; import { PwshModel } from '../utils/PwshModel'; import { Dictionary } from '@azure-tools/linq'; diff --git a/powershell/plugins/modifiers-v2.ts b/powershell/plugins/modifiers-v2.ts index 7ad674ad71..007c698777 100644 --- a/powershell/plugins/modifiers-v2.ts +++ b/powershell/plugins/modifiers-v2.ts @@ -3,19 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// import { codemodel, processCodeModel, allVirtualParameters, allVirtualProperties, ModelState, command } from '@azure-tools/codemodel-v3'; import { Host, Channel } from '@azure-tools/autorest-extension-base'; import { pascalCase, serialize } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { stat } from 'fs'; import { CommandOperation } from '../utils/command-operation'; // import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { PwshModel } from '../utils/PwshModel'; import { allVirtualParameters, allVirtualProperties } from '../utils/resolve-conflicts'; import { EnumValue } from '../utils/schema'; -type State = NewModelState; +type State = ModelState; let directives: Array = []; @@ -709,7 +708,7 @@ export async function applyModifiersV2(service: Host) { .where(directive => isWhereCommandDirective(directive) || isWhereModelDirective(directive) || isWhereEnumDirective(directive) || isRemoveCommandDirective(directive)) .toArray(); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); const result = await tweakModel(state); await service.WriteFile('code-model-v4-modifiers-v2.yaml', serialize(result), undefined, 'code-model-v4'); diff --git a/powershell/plugins/plugin-create-inline-properties.ts b/powershell/plugins/plugin-create-inline-properties.ts index 2d4227bd09..223d9c5f18 100644 --- a/powershell/plugins/plugin-create-inline-properties.ts +++ b/powershell/plugins/plugin-create-inline-properties.ts @@ -11,7 +11,7 @@ import { Host, Session, startSession } from '@azure-tools/autorest-extension-bas //import { CommandOperation } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; import { CommandOperation } from '../utils/command-operation'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { VirtualParameter } from '../utils/command-operation'; import { VirtualProperty, getAllProperties, getAllPublicVirtualProperties } from '../utils/schema'; import { resolveParameterNames } from '../utils/resolve-conflicts'; @@ -23,7 +23,7 @@ function getPluralizationService(): EnglishPluralizationService { return result; } -type State = NewModelState; +type State = ModelState; export function singularize(word: string): string { return getPluralizationService().singularize(word); @@ -397,7 +397,7 @@ async function createVirtuals(state: State): Promise { export async function createInlinedPropertiesPlugin(service: Host) { //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-create-virtual-properties-v2.yaml', serialize(await createVirtuals(state)), undefined, 'code-model-v4'); //return processCodeModel(createVirtuals, service, 'create-virtual-properties-v2'); } diff --git a/powershell/plugins/plugin-tweak-m4-model.ts b/powershell/plugins/plugin-tweak-m4-model.ts index 3a50303699..858c6f5f0e 100644 --- a/powershell/plugins/plugin-tweak-m4-model.ts +++ b/powershell/plugins/plugin-tweak-m4-model.ts @@ -5,13 +5,13 @@ import { ArraySchema, CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { StatusCodes } from '../utils/http-definitions'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Host } from '@azure-tools/autorest-extension-base'; -type State = NewModelState; +type State = ModelState; let directives: Array = []; @@ -171,6 +171,6 @@ function recursiveRemoveM4DefaultDescription(schema: Schema, visited: Set(service).init(); + const state = await new ModelState(service).init(); service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/plugin-tweak-model-azure-v2.ts b/powershell/plugins/plugin-tweak-model-azure-v2.ts index 9dde68f786..50f2ab1882 100644 --- a/powershell/plugins/plugin-tweak-model-azure-v2.ts +++ b/powershell/plugins/plugin-tweak-model-azure-v2.ts @@ -7,11 +7,11 @@ import { keys, length, values } from '@azure-tools/linq'; import { Channel, Host } from '@azure-tools/autorest-extension-base'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { PwshModel } from '../utils/PwshModel'; import { getAllProperties, ObjectSchema, Response, SchemaType, Schema } from '@azure-tools/codemodel'; import { serialize } from '@azure-tools/codegen'; -type State = NewModelState; +type State = ModelState; const xmsPageable = 'x-ms-pageable'; @@ -197,6 +197,6 @@ function getSchema(response: Response): Schema { // Additional tweaks the code model to adjust things so that the code will generate better. export async function tweakModelAzurePluginV2(service: Host) { - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-tweakcodemodelazure-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index bb2b2cdd56..4083a311e3 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -3,12 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Property, SealedChoiceSchema, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema, ConditionalValue } from '@azure-tools/codemodel'; -//import { ModelState } from '@azure-tools/codemodel-v3'; -//import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3'; import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen'; import { items, keys, values, Dictionary, length } from '@azure-tools/linq'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { defaultCipherList } from 'constants'; @@ -20,7 +18,7 @@ export enum HeaderPropertyType { Header = 'Header', HeaderAndBody = 'HeaderAndBody' } -type State = NewModelState; +type State = ModelState; // For now, we are not dynamically changing the service-name. Instead, we would figure out a method to change it during the creation of service readme's. @@ -637,7 +635,7 @@ async function tweakModelV2(state: State): Promise { export async function tweakModelPlugin(service: Host) { //const session = await startSession(service, {}, codeModelSchema); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); //const result = tweakModelV2(session); await service.WriteFile('code-model-v4-tweakcodemodel-v2.yaml', serialize(await tweakModelV2(state)), undefined, 'code-model-v4'); //return processCodeModel(tweakModelV2, service, 'tweakcodemodel-v2'); diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts index b92c5643a4..6d89881341 100644 --- a/powershell/plugins/powershell-v2.ts +++ b/powershell/plugins/powershell-v2.ts @@ -7,8 +7,7 @@ import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; import { Host } from '@azure-tools/autorest-extension-base'; import { join } from 'path'; -import { Project, NewProject } from '../internal/project'; -import { State } from '../internal/state'; +import { NewProject } from '../internal/project'; import { generatePsm1 } from '../generators/psm1'; import { generateCsproj } from '../generators/csproj'; import { generatePsm1Custom } from '../generators/psm1.custom'; diff --git a/powershell/plugins/ps-namer-v2.ts b/powershell/plugins/ps-namer-v2.ts index 39f28aee11..fdc15b97a9 100644 --- a/powershell/plugins/ps-namer-v2.ts +++ b/powershell/plugins/ps-namer-v2.ts @@ -11,10 +11,10 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import * as linq from '@azure-tools/linq'; import { singularize } from '../internal/name-inferrer'; import { PwshModel } from '../utils/PwshModel'; -import { NewModelState } from '../utils/model-state'; +import { ModelState } from '../utils/model-state'; import { allVirtualParameters, allVirtualProperties, resolveParameterNames, resolvePropertyNames } from '../utils/resolve-conflicts'; -type State = NewModelState; +type State = ModelState; function getCmdletName(verb: string, subjectPrefix: string, subject: string): string { return `${verb}-${subjectPrefix}${subject}`; @@ -208,6 +208,6 @@ export async function namerV2(service: Host) { //return processCodeModel(tweakModel, service, 'psnamer'); //const session = await startSession(service, {}, codeModelSchema); //const result = tweakModelV2(session); - const state = await new NewModelState(service).init(); + const state = await new ModelState(service).init(); await service.WriteFile('code-model-v4-psnamer-v2.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4'); } \ No newline at end of file diff --git a/powershell/test/operationId-inferring.ts b/powershell/test/operationId-inferring.ts index c2adcfee19..27d35348c0 100644 --- a/powershell/test/operationId-inferring.ts +++ b/powershell/test/operationId-inferring.ts @@ -7,7 +7,6 @@ import * as assert from 'assert'; import { suite, test } from 'mocha-typescript'; import * as pp from '../plugins/create-commands-v2'; -import { ModelState, JsonType, processCodeModel, codemodel, components, command, http, getAllProperties, } from '@azure-tools/codemodel-v3'; import { Channel, JsonPath, Mapping, RawSourceMap, Message } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; require('source-map-support').install(); diff --git a/powershell/utils/PwshModel.ts b/powershell/utils/PwshModel.ts index 2f200bc7df..acacaaa7d0 100644 --- a/powershell/utils/PwshModel.ts +++ b/powershell/utils/PwshModel.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { codeModelSchema, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext } from '@azure-tools/codemodel'; -//import { CommandComponents } from '@azure-tools/codemodel-v3/dist/code-model/command-operation'; import { DeepPartial } from '@azure-tools/codegen'; import { CommandComponents } from '../utils/command-operation'; diff --git a/powershell/utils/model-state.ts b/powershell/utils/model-state.ts index c51ff1e84e..d809d798f1 100644 --- a/powershell/utils/model-state.ts +++ b/powershell/utils/model-state.ts @@ -7,7 +7,7 @@ import { Channel, Host, JsonPath, Mapping, RawSourceMap, Message } from '@azure- import { safeEval, deserialize, Initializer, DeepPartial } from '@azure-tools/codegen'; import { Dictionary } from '@azure-tools/linq'; -export class NewModelState> extends Initializer { +export class ModelState> extends Initializer { public model!: T; protected documentName!: string; protected currentPath: JsonPath = new Array(); @@ -15,13 +15,13 @@ export class NewModelState> extends Initializer { private _debug = false; private _verbose = false; - public constructor(protected service: Host, objectInitializer?: DeepPartial>) { + public constructor(protected service: Host, objectInitializer?: DeepPartial>) { super(); this.apply(objectInitializer); } async init(project?: any) { - const m = await NewModelState.getModel(this.service); + const m = await ModelState.getModel(this.service); this.model = m.model; this.documentName = m.filename; this.initContext(project); From 8b89f5a19573c8c2ce103b4a8504f86251363587 Mon Sep 17 00:00:00 2001 From: derek Date: Fri, 16 Oct 2020 12:00:42 +0800 Subject: [PATCH 4/5] Remove the prefix New --- powershell/cmdlets/class.ts | 16 +- powershell/cmdlets/namespace.ts | 10 +- powershell/enums/namespace.ts | 6 +- powershell/generators/csproj.ts | 4 +- powershell/generators/gitattributes.ts | 4 +- powershell/generators/gitignore.ts | 4 +- powershell/generators/nuspec.ts | 4 +- powershell/generators/psm1.custom.ts | 4 +- powershell/generators/psm1.internal.ts | 4 +- powershell/generators/psm1.ts | 4 +- powershell/generators/readme.ts | 4 +- powershell/generators/script-cmdlet.ts | 4 +- powershell/internal/project.ts | 50 ++-- powershell/internal/state.ts | 10 +- powershell/llcsharp/code-model.ts | 10 +- powershell/llcsharp/enums/enum.ts | 10 +- powershell/llcsharp/enums/namespace.ts | 4 +- powershell/llcsharp/exports.ts | 2 +- powershell/llcsharp/generator.ts | 10 +- powershell/llcsharp/model/interface.ts | 10 +- .../llcsharp/model/model-class-dictionary.ts | 10 +- powershell/llcsharp/model/model-class-json.ts | 14 +- .../llcsharp/model/model-class-serializer.ts | 92 +------ powershell/llcsharp/model/model-class.ts | 72 ++--- powershell/llcsharp/model/namespace.ts | 46 ++-- powershell/llcsharp/model/property.ts | 10 +- powershell/llcsharp/operation/api-class.ts | 14 +- powershell/llcsharp/operation/method.ts | 82 ++---- powershell/llcsharp/operation/namespace.ts | 4 +- powershell/llcsharp/operation/parameter.ts | 24 +- powershell/llcsharp/project.ts | 16 +- powershell/llcsharp/schema/Uuid.ts | 17 +- powershell/llcsharp/schema/array.ts | 254 +----------------- powershell/llcsharp/schema/binary.ts | 78 +----- powershell/llcsharp/schema/boolean.ts | 19 +- powershell/llcsharp/schema/byte-array.ts | 108 +------- powershell/llcsharp/schema/char.ts | 33 +-- powershell/llcsharp/schema/date-time.ts | 178 +----------- powershell/llcsharp/schema/date.ts | 8 +- powershell/llcsharp/schema/duration.ts | 60 +---- powershell/llcsharp/schema/enum.ts | 24 +- .../schema/extended-type-declaration.ts | 49 +--- powershell/llcsharp/schema/integer.ts | 37 +-- powershell/llcsharp/schema/object.ts | 166 +----------- powershell/llcsharp/schema/primitive.ts | 187 +------------ powershell/llcsharp/schema/schema-resolver.ts | 38 +-- powershell/llcsharp/schema/string.ts | 194 +------------ powershell/llcsharp/validations.ts | 10 +- powershell/models/model-extensions.ts | 18 +- powershell/module/module-class.ts | 4 +- powershell/module/module-namespace.ts | 6 +- powershell/plugins/cs-namer-v2.ts | 6 +- powershell/plugins/llcsharp-v2.ts | 4 +- powershell/plugins/powershell-v2.ts | 6 +- powershell/utils/schema.ts | 14 +- 55 files changed, 298 insertions(+), 1778 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index 3a4cb6b964..ac300361fe 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -13,14 +13,14 @@ import { Access, Attribute, BackedProperty, Catch, Class, ClassType, Constructor, dotnet, Else, Expression, Finally, ForEach, If, LambdaProperty, LiteralExpression, LocalVariable, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Property, Return, Statements, BlockStatement, StringExpression, Switch, System, TerminalCase, toExpression, Try, Using, valueOf, Field, IsNull, Or, ExpressionOrLiteral, TerminalDefaultCase, xmlize, TypeDeclaration, And, IsNotNull, PartialMethod, Case } from '@azure-tools/codegen-csharp'; -import { ClientRuntime, EventListener, Schema, ArrayOf, NewArrayOf, EnumImplementation, NewEnumImplementation } from '../llcsharp/exports'; +import { ClientRuntime, EventListener, Schema, NewArrayOf, NewEnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; -import { NewState } from '../internal/state'; +import { State } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; import { IParameter } from '@azure-tools/codemodel-v3/dist/code-model/components'; import { IParameter as NewIParameter } from '../utils/components'; import { Variable, Local, ParameterModifier } from '@azure-tools/codegen-csharp'; -import { NewGetVirtualPropertyName } from '../llcsharp/model/model-class'; +import { getVirtualPropertyName } from '../llcsharp/model/model-class'; const PropertiesRequiringNew = new Set(['Host', 'Events']); @@ -287,9 +287,9 @@ export function NewAddInfoAttribute(targetProperty: Property, pType: TypeDeclara } -export class NewCmdletClass extends Class { +export class CmdletClass extends Class { private cancellationToken!: Expression; - public state: NewState; + public state: State; private readonly eventListener: EventListener; private readonly dropBodyParameter: boolean; private invocationInfo!: Property; @@ -307,7 +307,7 @@ export class NewCmdletClass extends Class { private hasStreamOutput: boolean; private outFileParameter?: Property; - constructor(namespace: Namespace, operation: CommandOperation, state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, operation: CommandOperation, state: State, objectInitializer?: DeepPartial) { // generate the 'variant' part of the name const noun = `${state.project.prefix}${operation.details.csharp.subjectPrefix}${operation.details.csharp.subject}`; const variantName = `${noun}${operation.details.csharp.name ? `_${operation.details.csharp.name}` : ''}`; @@ -1191,9 +1191,9 @@ export class NewCmdletClass extends Class { const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, (vParam.origin).property.language.csharp?.required, this.state).isNullable; const cmdletParameter = new Property(vParam.name, propertyType, { - get: toExpression(`${expandedBodyParameter.value}.${NewGetVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ + get: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name}${!nullable ? '' : ` ?? ${propertyType.defaultOfType}`}`), // /* ${inspect(vParam.origin)} */ // get: toExpression(`null == ${expandedBodyParameter.value}.${vParam.origin.name} ? ${propertyType.defaultOfType} : (${propertyType.declaration}) ${expandedBodyParameter.value}.${vParam.origin.name}`), - set: toExpression(`${expandedBodyParameter.value}.${NewGetVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), + set: toExpression(`${expandedBodyParameter.value}.${getVirtualPropertyName((vParam.origin)) || vParam.origin.name} = value`), new: PropertiesRequiringNew.has(vParam.name) ? Modifier.New : Modifier.None }); diff --git a/powershell/cmdlets/namespace.ts b/powershell/cmdlets/namespace.ts index 41046f3726..52a2c80d80 100644 --- a/powershell/cmdlets/namespace.ts +++ b/powershell/cmdlets/namespace.ts @@ -5,17 +5,17 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { Schema, ClientRuntime } from '../llcsharp/exports'; -import { NewState } from '../internal/state'; -import { NewCmdletClass } from './class'; +import { State } from '../internal/state'; +import { CmdletClass } from './class'; import { DeepPartial } from '@azure-tools/codegen'; -export class NewCmdletNamespace extends Namespace { +export class CmdletNamespace extends Namespace { inputModels = new Array(); public get outputFolder(): string { return this.state.project.cmdletFolder; } - constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: State, objectInitializer?: DeepPartial) { super('Cmdlets', parent); this.apply(objectInitializer); } @@ -29,7 +29,7 @@ export class NewCmdletNamespace extends Namespace { if (this.state.project.azure && operation.details.csharp.verb === 'Set' && operation.details.csharp.name.indexOf('ViaIdentity') > 0) { continue; } - this.addClass(await new NewCmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); + this.addClass(await new CmdletClass(this, operation, this.state.path('commands', 'operations', index)).init()); } return this; } diff --git a/powershell/enums/namespace.ts b/powershell/enums/namespace.ts index bc958d1729..d704c7b237 100644 --- a/powershell/enums/namespace.ts +++ b/powershell/enums/namespace.ts @@ -5,19 +5,19 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { EnumDetails } from '@azure-tools/codemodel-v3'; import { If, Parameter, Method, Namespace, System, Struct, Attribute, Class, dotnet, LambdaMethod, LiteralExpression, Modifier } from '@azure-tools/codegen-csharp'; -import { NewState } from '../internal/state'; +import { State } from '../internal/state'; import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, TypeConverterAttribute, PSTypeConverter } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; import { EnumDetails as NewEnumDetails } from '../utils/schema'; -export class NewEnumNamespace extends Namespace { +export class EnumNamespace extends Namespace { public get outputFolder(): string { return join(this.state.project.apiFolder, 'Support'); } - constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, public state: State, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); //const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []] diff --git a/powershell/generators/csproj.ts b/powershell/generators/csproj.ts index 84d3b71bc4..9f19683dbf 100644 --- a/powershell/generators/csproj.ts +++ b/powershell/generators/csproj.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateCsproj(project: NewProject) { +export async function generateCsproj(project: Project) { const release = project.azure ? ` true true MSSharedLibKey.snk diff --git a/powershell/generators/gitattributes.ts b/powershell/generators/gitattributes.ts index 165e310abe..e3467fba6c 100644 --- a/powershell/generators/gitattributes.ts +++ b/powershell/generators/gitattributes.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; -export async function generateGitAttributes(project: NewProject) { +export async function generateGitAttributes(project: Project) { project.state.writeFile(project.gitAttributes, '* text=auto', undefined, 'source-file-other'); } \ No newline at end of file diff --git a/powershell/generators/gitignore.ts b/powershell/generators/gitignore.ts index ef4d362f0c..f8e7cf3ee9 100644 --- a/powershell/generators/gitignore.ts +++ b/powershell/generators/gitignore.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; -export async function generateGitIgnore(project: NewProject) { +export async function generateGitIgnore(project: Project) { project.state.writeFile(project.gitIgnore, `bin obj .vs diff --git a/powershell/generators/nuspec.ts b/powershell/generators/nuspec.ts index d60fce6a8d..7e593cedbe 100644 --- a/powershell/generators/nuspec.ts +++ b/powershell/generators/nuspec.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; function removeCd(path: string): string { return path.startsWith('./') ? path.replace('./', '') : path; } -export async function generateNuspec(project: NewProject) { +export async function generateNuspec(project: Project) { const dependencies = project.azure ? ` diff --git a/powershell/generators/psm1.custom.ts b/powershell/generators/psm1.custom.ts index f493b41c00..7977240814 100644 --- a/powershell/generators/psm1.custom.ts +++ b/powershell/generators/psm1.custom.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; -export async function generatePsm1Custom(project: NewProject) { +export async function generatePsm1Custom(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Custom) || ''); const dllPath = relative(project.customFolder, project.dll); const internalPath = relative(project.customFolder, project.psm1Internal); diff --git a/powershell/generators/psm1.internal.ts b/powershell/generators/psm1.internal.ts index 6ce88de483..76911b9c45 100644 --- a/powershell/generators/psm1.internal.ts +++ b/powershell/generators/psm1.internal.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { Host } from '@azure-tools/autorest-extension-base'; -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; import { getProfileExportScript } from './psm1'; -export async function generatePsm1Internal(project: NewProject) { +export async function generatePsm1Internal(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1Internal) || ''); const dllPath = relative(project.internalFolder, project.dll); psm1.prepend('Generated', ` diff --git a/powershell/generators/psm1.ts b/powershell/generators/psm1.ts index f63e1f4eea..82b0fa54eb 100644 --- a/powershell/generators/psm1.ts +++ b/powershell/generators/psm1.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { PSScriptFile } from '../file-formats/psscript-file'; import { relative } from 'path'; @@ -40,7 +40,7 @@ export function getProfileExportScript(exportFolderScript: string, isAzure: bool `; } -export async function generatePsm1(project: NewProject) { +export async function generatePsm1(project: Project) { const psm1 = new PSScriptFile(await project.state.readFile(project.psm1) || ''); let azureInitialize = ''; if (project.azure) { diff --git a/powershell/generators/readme.ts b/powershell/generators/readme.ts index 79a5f2d87c..b8563b454f 100644 --- a/powershell/generators/readme.ts +++ b/powershell/generators/readme.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { MdFile } from '../file-formats/md-file'; -export async function generateReadme(project: NewProject) { +export async function generateReadme(project: Project) { const md = new MdFile(await project.state.readFile(project.readme) || ''); let azureInfo = ''; if (project.azure) { diff --git a/powershell/generators/script-cmdlet.ts b/powershell/generators/script-cmdlet.ts index b0839de113..741a1292cb 100644 --- a/powershell/generators/script-cmdlet.ts +++ b/powershell/generators/script-cmdlet.ts @@ -4,7 +4,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { serialize, indent, setIndentation, applyOverrides, pascalCase } from '@azure-tools/codegen'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; @@ -51,7 +51,7 @@ function getType(type: string) { return type; } -export async function generateScriptCmdlets(project: NewProject) { +export async function generateScriptCmdlets(project: Project) { const commands = await project.state.getValue>('command', []); for (const command of values(commands)) { if (!command.action) { diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index faf94d08c2..e8a730dcff 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewEnhancedTypeDeclaration, Boolean, NewBoolean, NewSchemaDefinitionResolver } from '../llcsharp/exports'; -import { NewState } from './state'; +import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewBoolean, SchemaDefinitionResolver } from '../llcsharp/exports'; +import { State } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { NewEnumNamespace } from '../enums/namespace'; -import { NewModelExtensionsNamespace } from '../models/model-extensions'; +import { EnumNamespace } from '../enums/namespace'; +import { ModelExtensionsNamespace } from '../models/model-extensions'; -import { NewModuleNamespace } from '../module/module-namespace'; -import { NewCmdletNamespace } from '../cmdlets/namespace'; +import { ModuleNamespace } from '../module/module-namespace'; +import { CmdletNamespace } from '../cmdlets/namespace'; import { Host } from '@azure-tools/autorest-extension-base'; import { codemodel, PropertyDetails, exportedModels as T } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; @@ -33,12 +33,6 @@ export interface Metadata { projectUri: string; } -export class PSSwitch extends Boolean { - get declaration(): string { - return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`; - } - -} export class NewPSSwitch extends NewBoolean { @@ -47,9 +41,9 @@ export class NewPSSwitch extends NewBoolean { } } -export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { +export class PSSchemaResolver extends SchemaDefinitionResolver { inResolve = false; - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { const before = this.inResolve; try { if (!this.inResolve) { @@ -69,7 +63,7 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver { } -export class NewProject extends codeDomProject { +export class Project extends codeDomProject { public azure!: boolean; public license!: string; public cmdletFolder!: string; @@ -102,7 +96,7 @@ export class NewProject extends codeDomProject { public apiFolder!: string; public baseFolder!: string; public moduleFolder!: string; - public schemaDefinitionResolver!: NewSchemaDefinitionResolver; + public schemaDefinitionResolver!: SchemaDefinitionResolver; public moduleVersion!: string; public profiles!: Array; @@ -110,19 +104,19 @@ export class NewProject extends codeDomProject { public subjectPrefix!: string; public projectNamespace!: string; public overrides!: Dictionary; - public serviceNamespace!: NewModuleNamespace; - public supportNamespace!: NewEnumNamespace; - public cmdlets!: NewCmdletNamespace; + public serviceNamespace!: ModuleNamespace; + public supportNamespace!: EnumNamespace; + public cmdlets!: CmdletNamespace; - public modelsExtensions!: NewModelExtensionsNamespace; + public modelsExtensions!: ModelExtensionsNamespace; public accountsVersionMinimum!: string; public dependencyModuleFolder!: string; public metadata!: Metadata; - public state!: NewState; + public state!: State; public helpLinkPrefix!: string; get model() { return this.state.model; } - constructor(protected service: Host, objectInitializer?: DeepPartial) { + constructor(protected service: Host, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } @@ -130,9 +124,9 @@ export class NewProject extends codeDomProject { public async init(): Promise { await super.init(); - this.state = await new NewState(this.service).init(this); + this.state = await new State(this.service).init(this); - this.schemaDefinitionResolver = new NewPSSchemaResolver(); + this.schemaDefinitionResolver = new PSSchemaResolver(); this.projectNamespace = this.state.model.language.csharp?.namespace || ''; @@ -207,20 +201,20 @@ export class NewProject extends codeDomProject { this.readme = `${this.baseFolder}/readme.md`; // add project namespace - this.serviceNamespace = new NewModuleNamespace(this.state); + this.serviceNamespace = new ModuleNamespace(this.state); this.serviceNamespace.header = this.license; this.addNamespace(this.serviceNamespace); - this.supportNamespace = new NewEnumNamespace(this.serviceNamespace, this.state); + this.supportNamespace = new EnumNamespace(this.serviceNamespace, this.state); this.supportNamespace.header = this.license; this.addNamespace(this.supportNamespace); - this.modelsExtensions = new NewModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); + this.modelsExtensions = new ModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); this.modelsExtensions.header = this.license; this.addNamespace(this.modelsExtensions); // add cmdlet namespace - this.cmdlets = await new NewCmdletNamespace(this.serviceNamespace, this.state).init(); + this.cmdlets = await new CmdletNamespace(this.serviceNamespace, this.state).init(); this.cmdlets.header = this.license; this.addNamespace(this.cmdlets); diff --git a/powershell/internal/state.ts b/powershell/internal/state.ts index 7366941c83..c5253f5095 100644 --- a/powershell/internal/state.ts +++ b/powershell/internal/state.ts @@ -6,7 +6,7 @@ import { codemodel } from '@azure-tools/codemodel-v3'; import { Host, JsonPath, Session } from '@azure-tools/autorest-extension-base'; -import { NewProject } from './project'; +import { Project } from './project'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { ModelState } from '../utils/model-state'; @@ -24,15 +24,15 @@ export interface GeneratorSettings { apiFolder: string; } -export class NewState extends ModelState { - project!: NewProject; +export class State extends ModelState { + project!: Project; - public constructor(service: Host, objectInitializer?: DeepPartial) { + public constructor(service: Host, objectInitializer?: DeepPartial) { super(service); this.apply(objectInitializer); } - async init(project?: NewProject) { + async init(project?: Project) { if (project) { this.project = project; } diff --git a/powershell/llcsharp/code-model.ts b/powershell/llcsharp/code-model.ts index 8dc2d75cac..e5e14bc05a 100644 --- a/powershell/llcsharp/code-model.ts +++ b/powershell/llcsharp/code-model.ts @@ -4,17 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { codemodel, command, components, exportedModels as T, http, schema } from '@azure-tools/codemodel-v3'; -import { NewModelInterface } from './model/interface'; -import { NewModelClass } from './model/model-class'; +import { ModelInterface } from './model/interface'; +import { ModelClass } from './model/model-class'; import { EnhancedTypeDeclaration } from './schema/extended-type-declaration'; // C# specific details for components export interface SchemaDetails extends schema.SchemaDetails { typeDeclaration?: EnhancedTypeDeclaration; - classImplementation?: NewModelClass; - interfaceImplementation?: NewModelInterface; - internalInterfaceImplementation?: NewModelInterface; + classImplementation?: ModelClass; + interfaceImplementation?: ModelInterface; + internalInterfaceImplementation?: ModelInterface; interfaceName?: string; internalInterfaceName?: string; fullInternalInterfaceName?: string; diff --git a/powershell/llcsharp/enums/enum.ts b/powershell/llcsharp/enums/enum.ts index aca6b1476e..6287f37edc 100644 --- a/powershell/llcsharp/enums/enum.ts +++ b/powershell/llcsharp/enums/enum.ts @@ -20,14 +20,14 @@ import { Property } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Struct } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; -import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { NewState } from '../generator'; +import { NewEnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { +export class EnumClass extends Struct implements EnhancedTypeDeclaration { implementation: NewEnumImplementation; get schema(): NewSchema { return this.implementation.schema; @@ -78,7 +78,7 @@ export class NewEnumClass extends Struct implements NewEnhancedTypeDeclaration { return this.implementation.isRequired; } - constructor(schemaWithFeatures: NewEnumImplementation, state: NewState, objectInitializer?: DeepPartial) { + constructor(schemaWithFeatures: NewEnumImplementation, state: State, objectInitializer?: DeepPartial) { if (!schemaWithFeatures.schema.language.csharp?.enum) { throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.language.csharp?.name}`); } diff --git a/powershell/llcsharp/enums/namespace.ts b/powershell/llcsharp/enums/namespace.ts index daf5c24d22..90e9a014d6 100644 --- a/powershell/llcsharp/enums/namespace.ts +++ b/powershell/llcsharp/enums/namespace.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Namespace } from '@azure-tools/codegen-csharp'; -import { NewState } from '../generator'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class SupportNamespace extends Namespace { - constructor(parent: Namespace, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private state: State, objectInitializer?: DeepPartial) { super('Support', parent); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/exports.ts b/powershell/llcsharp/exports.ts index af1d456250..1a2054d48d 100644 --- a/powershell/llcsharp/exports.ts +++ b/powershell/llcsharp/exports.ts @@ -13,4 +13,4 @@ export * from './schema/schema-resolver'; export * from './schema/extended-type-declaration'; export * from './model/model-class-serializer'; export * from './schema/enum'; -export { Boolean, NewBoolean } from './schema/boolean'; +export { NewBoolean } from './schema/boolean'; diff --git a/powershell/llcsharp/generator.ts b/powershell/llcsharp/generator.ts index d7f6d57f95..b24d9690c6 100644 --- a/powershell/llcsharp/generator.ts +++ b/powershell/llcsharp/generator.ts @@ -7,21 +7,21 @@ import { codeModelSchema } from '@azure-tools/codemodel'; import { Model } from './code-model'; import { Host, JsonPath, Session, startSession } from '@azure-tools/autorest-extension-base'; -import { NewProject } from './project'; +import { Project } from './project'; import { Dictionary } from '@azure-tools/linq'; import { DeepPartial } from '@azure-tools/codegen'; import { PwshModel } from '../utils/PwshModel'; import { ModelState } from '../utils/model-state'; -export class NewState extends ModelState { - project!: NewProject; +export class State extends ModelState { + project!: Project; - public constructor(service: Host, objectInitializer?: DeepPartial) { + public constructor(service: Host, objectInitializer?: DeepPartial) { super(service); this.apply(objectInitializer); } - async init(project?: NewProject) { + async init(project?: Project) { if (project) { this.project = project; } diff --git a/powershell/llcsharp/model/interface.ts b/powershell/llcsharp/model/interface.ts index c2db8c2512..e8be1b36e5 100644 --- a/powershell/llcsharp/model/interface.ts +++ b/powershell/llcsharp/model/interface.ts @@ -9,9 +9,9 @@ import { Expression, ExpressionOrLiteral, Interface, Namespace, OneOrMoreStateme import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, Language, ObjectSchema } from '@azure-tools/codemodel'; -import { NewState } from '../generator'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { NewModelClass } from './model-class'; +import { State } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; import { TypeContainer } from '@azure-tools/codegen-csharp'; import { DeepPartial } from '@azure-tools/codegen'; import { values } from '@azure-tools/linq'; @@ -125,7 +125,7 @@ export function newAddInfoAttribute(targetProperty: Property, pType: TypeDeclara -export class NewModelInterface extends Interface implements NewEnhancedTypeDeclaration { +export class ModelInterface extends Interface implements EnhancedTypeDeclaration { get schema(): NewSchema { return this.classImplementation.schema; } @@ -187,7 +187,7 @@ export class NewModelInterface extends Interface implements NewEnhancedTypeDecla // return this.classImplementation.hasHeaderProperties; return false; } - constructor(parent: TypeContainer, interfaceName: string, public classImplementation: NewModelClass, public state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: TypeContainer, interfaceName: string, public classImplementation: ModelClass, public state: State, objectInitializer?: DeepPartial) { super(parent, interfaceName); this.partial = true; this.apply(objectInitializer); diff --git a/powershell/llcsharp/model/model-class-dictionary.ts b/powershell/llcsharp/model/model-class-dictionary.ts index bf86350a3d..3b43e522eb 100644 --- a/powershell/llcsharp/model/model-class-dictionary.ts +++ b/powershell/llcsharp/model/model-class-dictionary.ts @@ -3,20 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Field, System, Property, toExpression, dotnet, Parameter, ParameterModifier, Method, Class, TypeDeclaration, Indexer, Access, Variable, Expression, If, And, ForEach, LocalVariable, ImplicitCastOperator } from '@azure-tools/codegen-csharp'; -import { NewModelClass } from './model-class'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; import { getAllVirtualProperties } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; import { DictionarySchema, ObjectSchema, SchemaType, Schema } from '@azure-tools/codemodel'; -export class NewDictionaryImplementation extends Class { +export class DictionaryImplementation extends Class { private get state() { return this.modelClass.state; } private get schema() { return this.modelClass.schema; } - public valueType!: TypeDeclaration | NewEnhancedTypeDeclaration; + public valueType!: TypeDeclaration | EnhancedTypeDeclaration; public ownsDictionary = false; - constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { + constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { super(modelClass.namespace, modelClass.name); this.apply(objectInitializer); } diff --git a/powershell/llcsharp/model/model-class-json.ts b/powershell/llcsharp/model/model-class-json.ts index eef5a46fa1..d404390842 100644 --- a/powershell/llcsharp/model/model-class-json.ts +++ b/powershell/llcsharp/model/model-class-json.ts @@ -24,22 +24,22 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { NewModelClass } from './model-class'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ModelClass } from './model-class'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; import { ObjectImplementation } from '../schema/object'; -import { NewModelInterface } from './interface'; +import { ModelInterface } from './interface'; -export class NewJsonSerializableClass extends Class { +export class JsonSerializableClass extends Class { private btj!: Method; private atj!: Method; private bfj!: Method; private afj!: Method; private excludes: string; - constructor(protected modelClass: NewModelClass, objectInitializer?: DeepPartial) { + constructor(protected modelClass: ModelClass, objectInitializer?: DeepPartial) { super(modelClass.namespace, modelClass.name); this.apply(objectInitializer); this.partial = true; @@ -88,7 +88,7 @@ export class NewJsonSerializableClass extends Class { // wildcard style deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, ${ClientRuntime.JsonSerializable}.DeserializeDictionary(()=>${System.Collections.Generic.Dictionary(System.String, System.Object).new()}),${exclusions.value} );`)); - } else if (vType instanceof NewModelInterface) { + } else if (vType instanceof ModelInterface) { // use the class of the dictionary value to deserialize values deserializeStatements.push(new Statements(`${ClientRuntime.JsonSerializable}.FromJson( json, ${ap}, (j) => ${vType.classImplementation.fullName}.FromJson(j) ,${exclusions.value} );`)); } else { @@ -100,7 +100,7 @@ export class NewJsonSerializableClass extends Class { for (const each of values(modelClass.backingFields)) { serializeStatements.add(`${each.field.value}?.ToJson(${container}, ${mode.use});`); - const sch = (each.typeDeclaration).schema; + const sch = (each.typeDeclaration).schema; const dictSchema = sch.type === SchemaType.Dictionary ? sch : sch.type === SchemaType.Object ? (sch).parents?.immediate.find((s) => s.type === SchemaType.Dictionary) : undefined; diff --git a/powershell/llcsharp/model/model-class-serializer.ts b/powershell/llcsharp/model/model-class-serializer.ts index be20242473..28caac5c53 100644 --- a/powershell/llcsharp/model/model-class-serializer.ts +++ b/powershell/llcsharp/model/model-class-serializer.ts @@ -23,55 +23,19 @@ import { Ternery } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { dotnet } from '@azure-tools/codegen-csharp'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { popTempVar, pushTempVar } from '../schema/primitive'; import { ObjectImplementation } from '../schema/object'; import { Schema } from '../code-model'; import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; -import { NewGetVirtualPropertyName } from './model-class'; +import { getVirtualPropertyName } from './model-class'; import { VirtualProperty as NewVirtualProperty } from '../../utils/schema'; -export class SerializationPartialClass extends Initializer { - constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, protected resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(); - this.apply(objectInitializer); - } - protected get virtualProperties() { - return this.schema.details.csharp.virtualProperties || { - owned: [], - inherited: [], - inlined: [] - }; - } - protected get allVirtualProperties() { - const vp = this.virtualProperties; - // return [...vp.owned, ...vp.inherited, ...vp.inlined]; - return values(vp.owned, vp.inherited, vp.inlined).toArray(); - } - - protected contentParameter = new Parameter('content', this.serializationType, { description: `The ${this.serializationType.declaration} content that should be used.` }); - protected refContainerParameter = new Parameter('container', this.serializationType, { modifier: ParameterModifier.Ref, description: `The ${this.serializationType.declaration} container that the serialization result will be placed in.` }); - protected returnNowParameter = new Parameter('returnNow', dotnet.Bool, { modifier: ParameterModifier.Ref, description: 'Determines if the rest of the serialization should be processed, or if the method should return instantly.' }); - - protected get typeCref() { - return ``; - } - - protected get thisCref() { - return ``; - } - - protected get interfaceCref() { - return ``; - } - -} - -export class NewSerializationPartialClass extends Initializer { - constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { +export class SerializationPartialClass extends Initializer { + constructor(protected targetClass: Class, protected targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, protected resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } @@ -107,10 +71,10 @@ export class NewSerializationPartialClass extends Initializer { } -export class NewDeserializerPartialClass extends NewSerializationPartialClass { +export class DeserializerPartialClass extends SerializationPartialClass { private beforeDeserialize!: Method; private afterDeserialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => NewEnhancedTypeDeclaration, objectInitializer?: DeepPartial) { + constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: NewSchema, resolver: (s: NewSchema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); this.apply(objectInitializer); } @@ -179,7 +143,7 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { const cvt = type.convertObjectMethod; const t = `((${virtualProperty.originalContainingSchema.language.csharp?.fullInternalInterfaceName})this)`; const tt = type ? `(${type.declaration})` : ''; - yield `${t}.${NewGetVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${NewGetVirtualPropertyName(virtualProperty)}",${t}.${NewGetVirtualPropertyName(virtualProperty)}, ${cvt});`; + yield `${t}.${getVirtualPropertyName(virtualProperty)} = ${tt} ${$this.contentParameter}.GetValueForProperty("${getVirtualPropertyName(virtualProperty)}",${t}.${getVirtualPropertyName(virtualProperty)}, ${cvt});`; } }; } @@ -218,46 +182,4 @@ export class NewDeserializerPartialClass extends NewSerializationPartialClass { } } -export class SerializerPartialClass extends SerializationPartialClass { - private beforeSerialize!: Method; - private afterSerialize!: Method; - constructor(targetClass: Class, targetInterface: TypeDeclaration, protected serializationType: TypeDeclaration, protected serializationFormat: string, protected schema: Schema, resolver: (s: Schema, req: boolean) => EnhancedTypeDeclaration, objectInitializer?: DeepPartial) { - super(targetClass, targetInterface, serializationType, serializationFormat, schema, resolver); - this.apply(objectInitializer); - } - - async init() { - this.addPartialMethods(); - this.addSerializer(); - - } - - protected addSerializer() { - const serializeMethod = this.targetClass.addMethod(new Method(`SerializeTo${this.serializationFormat}`, this.serializationType, { - parameters: [this.refContainerParameter], - description: `Serializes this instance of ${this.thisCref} into a ${this.typeCref}.`, - returnsDescription: `a serialized instance of ${this.thisCref} /> as a ${this.typeCref}.` - })); - - } - - protected addPartialMethods() { - const before = `BeforeSerialize${this.serializationFormat}`; - const after = `AfterSerialize${this.serializationFormat}`; - // add partial methods for future customization - this.beforeSerialize = this.targetClass.addMethod(new PartialMethod(before, dotnet.Void, { - access: Access.Default, - parameters: [this.refContainerParameter, this.returnNowParameter], - description: `${before} will be called before the serialization has commenced, allowing complete customization of the object before it is serialized. - If you wish to disable the default serialization entirely, return true in the output parameter. - Implement this method in a partial class to enable this behavior.` - })); - - this.afterSerialize = this.targetClass.addMethod(new PartialMethod(after, dotnet.Void, { - access: Access.Default, - parameters: [this.refContainerParameter], - description: `${after} will be called after the serialization has finished, allowing customization of the ${this.typeCref} before it is returned. Implement this method in a partial class to enable this behavior ` - })); - } -} diff --git a/powershell/llcsharp/model/model-class.ts b/powershell/llcsharp/model/model-class.ts index 5a420b37a3..fd98f5310a 100644 --- a/powershell/llcsharp/model/model-class.ts +++ b/powershell/llcsharp/model/model-class.ts @@ -8,22 +8,22 @@ import { camelCase, deconstruct, DeepPartial } from '@azure-tools/codegen'; import { items, values } from '@azure-tools/linq'; import { Access, Class, Constructor, Expression, ExpressionOrLiteral, Field, If, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Statements, System, TypeDeclaration, valueOf, Variable, BackedProperty, Property, Virtual, toExpression, StringExpression, LiteralExpression, Attribute } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { NewState } from '../generator'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { NewModelInterface } from './interface'; -import { NewJsonSerializableClass } from './model-class-json'; -import { NewModelProperty } from './property'; +import { State } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ObjectImplementation } from '../schema/object'; +import { ModelInterface } from './interface'; +import { JsonSerializableClass } from './model-class-json'; +import { ModelProperty } from './property'; import { PropertyOriginAttribute, DoNotFormatAttribute, FormatTableAttribute } from '../csharp-declarations'; import { Schema } from '../code-model'; -import { NewDictionaryImplementation } from './model-class-dictionary'; +import { DictionaryImplementation } from './model-class-dictionary'; import { Languages, Language, Schema as NewSchema, SchemaType, ObjectSchema, DictionarySchema } from '@azure-tools/codemodel'; import { VirtualProperty as NewVirtualProperty, getAllVirtualProperties as newGetAllVirtualProperties } from '../../utils/schema'; -export function NewGetVirtualPropertyName(vp?: NewVirtualProperty): string { +export function getVirtualPropertyName(vp?: NewVirtualProperty): string { if (vp && vp.accessViaMember && vp.accessViaProperty?.accessViaMember) { - return NewGetVirtualPropertyName(vp.accessViaMember); + return getVirtualPropertyName(vp.accessViaMember); } return vp ? vp.name : ''; } @@ -34,7 +34,7 @@ export interface BackingField { className: string; } -export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { +export class ModelClass extends Class implements EnhancedTypeDeclaration { deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { return this.featureImplementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); } @@ -83,26 +83,26 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { public get schema() { return this.featureImplementation.schema; } /* @internal */ validateMethod?: Method; - /* @internal */ discriminators: Map = new Map(); - /* @internal */ parentModelClasses: Array = new Array(); - /* @internal */ get modelInterface(): NewModelInterface { return this.schema.language.csharp?.interfaceImplementation; } - /* @internal */ get internalModelInterface(): NewModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } + /* @internal */ discriminators: Map = new Map(); + /* @internal */ parentModelClasses: Array = new Array(); + /* @internal */ get modelInterface(): ModelInterface { return this.schema.language.csharp?.interfaceImplementation; } + /* @internal */ get internalModelInterface(): ModelInterface { return this.schema.language.csharp?.internalInterfaceImplementation; } - /* @internal */ state: NewState; + /* @internal */ state: State; /* @internal */ backingFields = new Array(); - /* @internal */ featureImplementation: NewObjectImplementation; + /* @internal */ featureImplementation: ObjectImplementation; /* @internal */ validationEventListener: Parameter = new Parameter('eventListener', ClientRuntime.IEventListener, { description: `an instance that will receive validation events.` }); - /* @internal */ jsonSerializer?: NewJsonSerializableClass; + /* @internal */ jsonSerializer?: JsonSerializableClass; // /* @internal */ xmlSerializer?: XmlSerializableClass; - /* @internal */ dictionaryImpl?: NewDictionaryImplementation; + /* @internal */ dictionaryImpl?: DictionaryImplementation; private readonly validationStatements = new Statements(); - public ownedProperties = new Array(); - private pMap = new Map(); + public ownedProperties = new Array(); + private pMap = new Map(); // public hasHeaderProperties: boolean; - constructor(namespace: Namespace, schemaWithFeatures: NewObjectImplementation, state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, schemaWithFeatures: ObjectImplementation, state: State, objectInitializer?: DeepPartial) { super(namespace, schemaWithFeatures.schema.language.csharp?.name || ''); this.featureImplementation = schemaWithFeatures; this.schema.language.csharp = this.schema.language.csharp || new Language(); @@ -121,13 +121,13 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // create an interface for this model class if (!this.schema.language.csharp.interfaceImplementation) { - (this.schema.language.csharp.interfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.interfaceName || `I${this.schema.language.csharp.name}`, this, this.state)); + (this.schema.language.csharp.interfaceImplementation = new ModelInterface(this.namespace, this.schema.language.csharp.interfaceName || `I${this.schema.language.csharp.name}`, this, this.state)); } this.interfaces.push(this.modelInterface); if (!this.schema.language.csharp.internalInterfaceImplementation) { - (this.schema.language.csharp.internalInterfaceImplementation = new NewModelInterface(this.namespace, this.schema.language.csharp.internalInterfaceName || `I${this.schema.language.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); + (this.schema.language.csharp.internalInterfaceImplementation = new ModelInterface(this.namespace, this.schema.language.csharp.internalInterfaceName || `I${this.schema.language.csharp.name}Internal`, this, this.state, { accessModifier: Access.Internal })); } @@ -145,7 +145,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const dictSchema = (this.schema).type === SchemaType.Dictionary ? this.schema : this.schema.parents?.immediate?.find((schema) => schema.type === SchemaType.Dictionary); if (dictSchema) { - this.dictionaryImpl = new NewDictionaryImplementation(this).init(); + this.dictionaryImpl = new DictionaryImplementation(this).init(); } } @@ -160,7 +160,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { this.addHeaderDeserializer(); if (this.state.project.jsonSerialization) { - this.jsonSerializer = new NewJsonSerializableClass(this); + this.jsonSerializer = new JsonSerializableClass(this); } } @@ -168,11 +168,11 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { if (virtualProperty.accessViaProperty) { if (virtualProperty.accessViaProperty.accessViaProperty) { // return `/*1*/${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}.${this.nested(virtualProperty.accessViaProperty.accessViaProperty, internal)}`; } } //return `/*2*/${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember)}`; } private accessor(virtualProperty: NewVirtualProperty, internal = false): string { @@ -181,11 +181,11 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const containingProperty = this.pMap.get(virtualProperty.accessViaProperty); if (containingProperty && virtualProperty.accessViaMember) { //return `/*3*/((${virtualProperty.accessViaMember.originalContainingSchema.details.csharp.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; - return `((${virtualProperty.accessViaMember.originalContainingSchema.language.csharp?.fullInternalInterfaceName})${containingProperty.name}${prefix}).${NewGetVirtualPropertyName(virtualProperty.accessViaMember)}`; + return `((${virtualProperty.accessViaMember.originalContainingSchema.language.csharp?.fullInternalInterfaceName})${containingProperty.name}${prefix}).${getVirtualPropertyName(virtualProperty.accessViaMember)}`; } } // return `/*4* ${virtualProperty.name}/${virtualProperty.accessViaMember?.name}/${virtualProperty.accessViaProperty?.name} */${getVirtualPropertyName(virtualProperty.accessViaMember) || '/*!!*/' + virtualProperty.name}`; - return `${NewGetVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; + return `${getVirtualPropertyName(virtualProperty.accessViaMember) || virtualProperty.name}`; } private createProperties() { @@ -224,7 +224,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const decl = this.state.project.modelsNamespace.NewResolveTypeDeclaration(actualProperty.schema, actualProperty.language.csharp?.required, this.state.path('schema')); /* public property */ - const myProperty = new NewModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.language.csharp?.required, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), { + const myProperty = new ModelProperty(virtualProperty.name, actualProperty.schema, actualProperty.language.csharp?.required, actualProperty.serializedName, actualProperty.language.csharp?.description || '', this.state.path('properties', n++), { initializer: actualProperty.language.csharp?.constantValue ? typeof actualProperty.language.csharp.constantValue === 'string' ? new StringExpression(actualProperty.language.csharp.constantValue) : new LiteralExpression(actualProperty.language.csharp.constantValue) : undefined }); @@ -404,12 +404,12 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { const aState = this.state.path('allOf', eachSchemaIndex); const td = this.state.project.modelsNamespace.NewResolveTypeDeclaration(aSchema, true, aState); - const parentClass = (aSchema.language.csharp?.classImplementation); + const parentClass = (aSchema.language.csharp?.classImplementation); const className = parentClass.fullName; const fieldName = camelCase(deconstruct(className.replace(/^.*\./, ''))); // add the interface as a parent to our interface. - const iface = aSchema.language.csharp?.interfaceImplementation; + const iface = aSchema.language.csharp?.interfaceImplementation; // add a field for the inherited values const backingField = this.addField(new Field(`__${fieldName}`, td, { initialValue: `new ${className}()`, access: Access.Private, description: `Backing field for Inherited model ` })); @@ -421,13 +421,13 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { this.validationStatements.add(td.validatePresence(this.validationEventListener, backingField)); this.validationStatements.add(td.validateValue(this.validationEventListener, backingField)); - this.internalModelInterface.interfaces.push(aSchema.language.csharp?.internalInterfaceImplementation); + this.internalModelInterface.interfaces.push(aSchema.language.csharp?.internalInterfaceImplementation); this.modelInterface.interfaces.push(iface); // const addlPropType = this.additionalPropertiesType(aSchema); if (addlPropType) { - this.dictionaryImpl = new NewDictionaryImplementation(this).init(addlPropType, backingField); + this.dictionaryImpl = new DictionaryImplementation(this).init(addlPropType, backingField); hasAdditionalPropertiesInParent = true; } } @@ -453,7 +453,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { // ensure the parent schema has it's class created first. this.state.project.modelsNamespace.NewResolveTypeDeclaration(parentSchema, true, aState); - const parentClass = parentSchema.language.csharp?.classImplementation; + const parentClass = parentSchema.language.csharp?.classImplementation; if (parentClass.isPolymorphic) { // remember this class for later. this.parentModelClasses.push(parentClass); @@ -495,7 +495,7 @@ export class NewModelClass extends Class implements NewEnhancedTypeDeclaration { return this.featureImplementation.validatePresence(eventListener, property); } - public addDiscriminator(discriminatorValue: string, modelClass: NewModelClass) { + public addDiscriminator(discriminatorValue: string, modelClass: ModelClass) { this.discriminators.set(discriminatorValue, modelClass); // tell any polymorphic parents incase we're doing subclass of a subclass. diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index f6e2bdfe75..3950e2ab9c 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -8,15 +8,15 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; -import { NewState } from '../generator'; -import { EnumImplementation, NewEnumImplementation } from '../schema/enum'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { ObjectImplementation, NewObjectImplementation } from '../schema/object'; -import { NewSchemaDefinitionResolver } from '../schema/schema-resolver'; -import { NewEnumClass } from '../enums/enum'; +import { State } from '../generator'; +import { NewEnumImplementation } from '../schema/enum'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { ObjectImplementation } from '../schema/object'; +import { SchemaDefinitionResolver } from '../schema/schema-resolver'; +import { EnumClass } from '../enums/enum'; import * as validation from '../validations'; -import { NewModelInterface } from './interface'; -import { NewModelClass } from './model-class'; +import { ModelInterface } from './interface'; +import { ModelClass } from './model-class'; import { DeepPartial } from '@azure-tools/codegen'; @@ -32,12 +32,12 @@ class ApiVersionNamespace extends Namespace { } } -export class NewModelsNamespace extends Namespace { +export class ModelsNamespace extends Namespace { private subNamespaces = new Dictionary(); - resolver = new NewSchemaDefinitionResolver(); - newResolver = new NewSchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: NewSchemas, private state: NewState, objectInitializer?: DeepPartial) { + resolver = new SchemaDefinitionResolver(); + newResolver = new SchemaDefinitionResolver(); + constructor(parent: Namespace, private schemas: NewSchemas, private state: State, objectInitializer?: DeepPartial) { super('Models', parent); this.subNamespaces[this.fullName] = this; @@ -50,29 +50,29 @@ export class NewModelsNamespace extends Namespace { if (schemas.objects) { for (const schema of schemas.objects) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.dictionaries) { for (const schema of schemas.dictionaries) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.any) { for (const schema of schemas.any) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.strings) { for (const schema of schemas.strings) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } if (schemas.sealedChoices) { for (const schema of schemas.sealedChoices) { - this.NewResolveTypeDeclaration(schema, true, state); + this.NewResolveTypeDeclaration(schema, true, state); } } //todo, need to add support for other types @@ -83,7 +83,7 @@ export class NewModelsNamespace extends Namespace { return 'Models'; } - public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: NewState): NewEnhancedTypeDeclaration { + public NewResolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: State): EnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -91,7 +91,7 @@ export class NewModelsNamespace extends Namespace { const td = this.newResolver.resolveTypeDeclaration(schema, required, state); if (!schema.language.csharp?.skip) { - if (td instanceof NewObjectImplementation) { + if (td instanceof ObjectImplementation) { // it's a class object. // create it if necessary @@ -99,10 +99,10 @@ export class NewModelsNamespace extends Namespace { const ns = this.subNamespaces[fullname] || this.add(new ApiVersionNamespace(fullname)); - const mc = schema.language.csharp?.classImplementation || new NewModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); + const mc = schema.language.csharp?.classImplementation || new ModelClass(ns, td, this.state, { description: schema.language.csharp?.description }); // this gets implicity created during class creation: - return schema.language.csharp?.interfaceImplementation; + return schema.language.csharp?.interfaceImplementation; } if (state.project.azure && /^api-?version$/i.exec(schema.language.csharp?.name || '')) { @@ -113,8 +113,8 @@ export class NewModelsNamespace extends Namespace { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { - new NewEnumClass(td, state); - // return schema.language.csharp.typeDeclaration = ec[0]; + new EnumClass(td, state); + // return schema.language.csharp.typeDeclaration = ec[0]; } } schema.language.csharp = schema.language.csharp || new Language(); diff --git a/powershell/llcsharp/model/property.ts b/powershell/llcsharp/model/property.ts index c17561d301..94a82a74ee 100644 --- a/powershell/llcsharp/model/property.ts +++ b/powershell/llcsharp/model/property.ts @@ -11,14 +11,14 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Property, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { NewState } from '../generator'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; -export class NewModelProperty extends BackedProperty implements EnhancedVariable { +export class ModelProperty extends BackedProperty implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { return this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this); @@ -58,10 +58,10 @@ export class NewModelProperty extends BackedProperty implements EnhancedVariable // public IsHeaderProperty: boolean; public schema: NewSchema; public serializedName: string; - private typeDeclaration: NewEnhancedTypeDeclaration; + private typeDeclaration: EnhancedTypeDeclaration; public language: any; - constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, schema: NewSchema, isRequired: boolean, serializedName: string, description: string, state: State, objectInitializer?: DeepPartial) { const decl = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, isRequired, state.path('schema')); super(name, decl); this.typeDeclaration = decl; diff --git a/powershell/llcsharp/operation/api-class.ts b/powershell/llcsharp/operation/api-class.ts index 86a06dbc78..1d66df80f6 100644 --- a/powershell/llcsharp/operation/api-class.ts +++ b/powershell/llcsharp/operation/api-class.ts @@ -6,15 +6,15 @@ import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Class, Namespace } from '@azure-tools/codegen-csharp'; -import { NewState } from '../generator'; -import { NewOperationMethod, NewCallMethod, NewValidationMethod } from '../operation/method'; +import { State } from '../generator'; +import { OperationMethod, CallMethod, ValidationMethod } from '../operation/method'; import { ParameterLocation } from '@azure-tools/codemodel-v3'; import { DeepPartial } from '@azure-tools/codegen'; export class ApiClass extends Class { // protected sender: Property; - constructor(namespace: Namespace, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, protected state: State, objectInitializer?: DeepPartial) { super(namespace, state.model.language.csharp?.name || ''); this.apply(objectInitializer); @@ -26,25 +26,25 @@ export class ApiClass extends Class { // todo for (const operationGroup of state.model.operationGroups) { for (const operation of operationGroup.operations) { - const operationMethod = new NewOperationMethod(this, operation, false, state); + const operationMethod = new OperationMethod(this, operation, false, state); this.addMethod(operationMethod); // Compare with m3, m4 operation has one more parameter called '$host'. We should skip it const parameters = operation.parameters?.filter((param) => param.language.default.serializedName !== '$host'); if ([...values(parameters).select(each => each.protocol.http?.in === ParameterLocation.Path)].length > 0) { // method has parameters in the path, so it could support '...ViaIdentity' - const identityMethod = new NewOperationMethod(this, operation, true, state); + const identityMethod = new OperationMethod(this, operation, true, state); identityMethod.emitCall(false); this.addMethod(identityMethod); } // check if this exact method is been created before (because _call and _validate have less specific parameters than the api) - const cm = new NewCallMethod(this, operationMethod, state); + const cm = new CallMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(cm)) { this.addMethod(cm); } - const vm = new NewValidationMethod(this, operationMethod, state); + const vm = new ValidationMethod(this, operationMethod, state); if (!this.hasMethodWithSameDeclaration(vm)) { this.addMethod(vm); } diff --git a/powershell/llcsharp/operation/method.ts b/powershell/llcsharp/operation/method.ts index 9911aec1d0..aa4e652131 100644 --- a/powershell/llcsharp/operation/method.ts +++ b/powershell/llcsharp/operation/method.ts @@ -24,8 +24,8 @@ import { Using } from '@azure-tools/codegen-csharp'; import { Local, LocalVariable, Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { HttpOperation, Schema } from '../code-model'; -import { NewState } from '../generator'; -import { NewCallbackParameter, NewOperationParameter, NewOperationBodyParameter } from '../operation/parameter'; +import { State } from '../generator'; +import { CallbackParameter, OperationParameter, OperationBodyParameter } from '../operation/parameter'; import { isMediaTypeJson, isMediaTypeXml, KnownMediaType, knownMediaType, normalizeMediaType, parseMediaType } from '@azure-tools/codemodel-v3'; import { ClassType, dotnet, System } from '@azure-tools/codegen-csharp'; @@ -33,7 +33,7 @@ import { Ternery } from '@azure-tools/codegen-csharp'; -function newRemoveEncoding(pp: NewOperationParameter, paramName: string, kmt: KnownMediaType): string { +function removeEncoding(pp: OperationParameter, paramName: string, kmt: KnownMediaType): string { const up = pp.typeDeclaration.serializeToNode(kmt, pp, paramName, ClientRuntime.SerializationMode.None).value; return pp.param.extensions && pp.param.extensions['x-ms-skip-url-encoding'] ? up.replace(/global::System.Uri.EscapeDataString|System.Uri.EscapeDataString/g, '') : up; } @@ -75,17 +75,17 @@ export class EventListener { } -export class NewOperationMethod extends Method { - public methodParameters: Array; - public bodyParameter?: NewOperationBodyParameter; +export class OperationMethod extends Method { + public methodParameters: Array; + public bodyParameter?: OperationBodyParameter; public contextParameter!: Parameter; public senderParameter!: Parameter; public resourceUri!: Parameter; - public callbacks = new Array(); + public callbacks = new Array(); protected callName: string; - constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(public parent: Class, public operation: Operation, public viaIdentity: boolean, protected state: State, objectInitializer?: DeepPartial) { super(viaIdentity ? `${operation.language.csharp?.name}ViaIdentity` : operation.language.csharp?.name || '', System.Threading.Tasks.Task()); this.apply(objectInitializer); this.async = Modifier.Async; @@ -110,7 +110,7 @@ export class NewOperationMethod extends Method { baseUrl = value.clientDefaultValue; continue; } - const p = new NewOperationParameter(this, value, this.state.path('parameters', index)); + const p = new OperationParameter(this, value, this.state.path('parameters', index)); if (value.language.csharp?.constantValue) { const constTd = state.project.modelsNamespace.NewResolveTypeDeclaration(value.schema, true, state); @@ -135,7 +135,7 @@ export class NewOperationMethod extends Method { // this request does have a request body. const param = this.operation.requests[0].parameters.find((p) => !p.origin || p.origin.indexOf('modelerfour:synthesized') < 0); if (param) { - this.bodyParameter = new NewOperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { + this.bodyParameter = new OperationBodyParameter(this, 'body', param.language.default.description, param.schema, param.required ?? false, this.state, { // TODO: temp solution. We need a class like NewKnowMediaType mediaType: knownMediaType(KnownMediaType.Json), contentType: KnownMediaType.Json @@ -147,7 +147,7 @@ export class NewOperationMethod extends Method { for (const response of [...values(this.operation.responses), ...values(this.operation.exceptions)]) { const responseType = (response).schema ? state.project.modelsNamespace.NewResolveTypeDeclaration(((response).schema), true, state) : null; const headerType = response.language.default.headerSchema ? state.project.modelsNamespace.NewResolveTypeDeclaration(response.language.default.headerSchema, true, state) : null; - const newCallbackParameter = new NewCallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); + const newCallbackParameter = new CallbackParameter(response.language.csharp?.name || '', responseType, headerType, this.state, { description: response.language.csharp?.description }); this.addParameter(newCallbackParameter); this.callbacks.push(newCallbackParameter); @@ -196,7 +196,7 @@ export class NewOperationMethod extends Method { + "`); } else { url = url.replace(`{${pp.param.language.default.serializedName}}`, `" - + ${newRemoveEncoding(pp, '', KnownMediaType.UriParameter)} + + ${removeEncoding(pp, '', KnownMediaType.UriParameter)} + "`); } } @@ -230,7 +230,7 @@ export class NewOperationMethod extends Method { initializer: System.Uri.new(`${System.Text.RegularExpressions.Regex.declaration}.Replace( "${url}" ${queryParams.length > 0 ? '+ "?"' : ''}${queryParams.joinWith(pp => ` - + ${newRemoveEncoding(pp, pp.param.language.default.serializedName, KnownMediaType.QueryParameter)}`, ` + + ${removeEncoding(pp, pp.param.language.default.serializedName, KnownMediaType.QueryParameter)}`, ` + "&"` )} ,"\\\\?&*$|&*$|(\\\\?)&+|(&)&+","$1$2")`.replace(/\s*\+ ""/gm, '')) @@ -292,9 +292,9 @@ export class NewOperationMethod extends Method { } } } -export class NewCallMethod extends Method { +export class CallMethod extends Method { public returnNull = false; - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { super(`${opMethod.name}_Call`, System.Threading.Tasks.Task()); this.description = `Actual wire call for method.`; this.returnsDescription = opMethod.returnsDescription; @@ -334,9 +334,9 @@ export class NewCallMethod extends Method { if (responses.protocol.http?.statusCodes[0] !== 'default') { const responseCode = responses.protocol.http?.statusCodes[0]; // will use enum when it can, fall back to casting int when it can't - yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); + yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `(${System.Net.HttpStatusCode.declaration})${responseCode}`, $this.responsesEmitter($this, opMethod, [responses], eventListener)); } else { - yield DefaultCase($this.NewResponsesEmitter($this, opMethod, [responses], eventListener)); + yield DefaultCase($this.responsesEmitter($this, opMethod, [responses], eventListener)); } } @@ -568,42 +568,12 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield 'break;'; } - private * responsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { - if (length(responses) > 1) { - yield Switch('_contentType', function* () { - for (const eachResponse of values(responses)) { - const mimetype = length(eachResponse.mimeTypes) > 0 ? eachResponse.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.details.csharp.name); - - let count = length(eachResponse.mimeTypes); - for (const mt of values(eachResponse.mimeTypes)) { - count--; - const mediaType = normalizeMediaType(mt); - if (mediaType) { - if (count === 0) { - yield Case(new StringExpression(mediaType).toString(), $this.responseHandler(mimetype, eachResponse, callbackParameter)); - } else { - yield TerminalCase(new StringExpression(mediaType).toString(), ''); - } - } - } - } - }); - } else { - const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.details.csharp.name); - // all mimeTypes per for this response code. - yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); - yield $this.responseHandler(values(response.mimeTypes).first() || '', response, callbackParameter); - } - } - - private * NewResponsesEmitter($this: NewCallMethod, opMethod: NewOperationMethod, responses: Array, eventListener: EventListener) { + private * responsesEmitter($this: CallMethod, opMethod: OperationMethod, responses: Array, eventListener: EventListener) { if (length(responses) > 1) { yield Switch('_contentType', function* () { for (const eachResponse of values(responses)) { const mimetype = length(eachResponse.protocol.http?.mediaTypes) > 0 ? eachResponse.protocol.http?.mimeTypes[0] : ''; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); + const callbackParameter = values(opMethod.callbacks).first(each => each.name === eachResponse.language.csharp?.name); let count = length(eachResponse.protocol.http?.mediaTypes); for (const mt of values(eachResponse.protocol.http?.mediaTypes)) { @@ -621,14 +591,14 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) }); } else { const response = responses[0]; - const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); + const callbackParameter = values(opMethod.callbacks).first(each => each.name === response.language.csharp?.name); // all mimeTypes per for this response code. yield eventListener.signal(ClientRuntime.Events.BeforeResponseDispatch, '_response'); yield $this.NewResponseHandler(values(response.protocol.http?.mediaTypes).first() || '', response, callbackParameter); } } - private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: NewCallbackParameter) { + private * responseHandlerForNormalPipeline(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { const callbackParameters = new Array(); if (callbackParameter.responseType) { @@ -656,7 +626,7 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.details.csharp.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: NewCallbackParameter) { + private * NewResponseHandlerForNormalPipeline(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { const callbackParameters = new Array(); if (callbackParameter.responseType) { @@ -684,16 +654,16 @@ if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK}) yield `await ${eachResponse.language.csharp?.name}(_response${callbackParameters.length === 0 ? '' : ','}${callbackParameters.joinWith(valueOf)});`; } - private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: NewCallbackParameter) { + private responseHandler(mimetype: string, eachResponse: NewResponse, callbackParameter: CallbackParameter) { return this.responseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); } - private NewResponseHandler(mimetype: string, eachResponse: Response, callbackParameter: NewCallbackParameter) { + private NewResponseHandler(mimetype: string, eachResponse: Response, callbackParameter: CallbackParameter) { return this.NewResponseHandlerForNormalPipeline(mimetype, eachResponse, callbackParameter); } } -export class NewValidationMethod extends Method { +export class ValidationMethod extends Method { - constructor(protected parent: Class, protected opMethod: NewOperationMethod, protected state: NewState, objectInitializer?: DeepPartial) { + constructor(protected parent: Class, protected opMethod: OperationMethod, protected state: State, objectInitializer?: DeepPartial) { super(`${opMethod.name}_Validate`, System.Threading.Tasks.Task()); this.apply(objectInitializer); this.description = `Validation method for method. Call this like the actual call, but you will get validation events back.`; diff --git a/powershell/llcsharp/operation/namespace.ts b/powershell/llcsharp/operation/namespace.ts index c90f2d949a..22f6a2736a 100644 --- a/powershell/llcsharp/operation/namespace.ts +++ b/powershell/llcsharp/operation/namespace.ts @@ -6,11 +6,11 @@ import { ImportDirective } from '@azure-tools/codegen-csharp'; import { Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; -import { NewState } from '../generator'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; export class ServiceNamespace extends Namespace { - constructor(public state: NewState, objectInitializer?: DeepPartial) { + constructor(public state: State, objectInitializer?: DeepPartial) { super(state.model.language.csharp?.namespace, state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); diff --git a/powershell/llcsharp/operation/parameter.ts b/powershell/llcsharp/operation/parameter.ts index 546325a446..e46c779bed 100644 --- a/powershell/llcsharp/operation/parameter.ts +++ b/powershell/llcsharp/operation/parameter.ts @@ -15,18 +15,18 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { HttpOperationParameter, Schema } from '../code-model'; import { EnhancedVariable } from '../extended-variable'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from '../schema/extended-type-declaration'; -import { NewState } from '../generator'; +import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; +import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; /** represents a method parameter for an http operation (header/cookie/query/path) */ -export class NewOperationParameter extends Parameter implements EnhancedVariable { - public typeDeclaration: NewEnhancedTypeDeclaration; +export class OperationParameter extends Parameter implements EnhancedVariable { + public typeDeclaration: EnhancedTypeDeclaration; public param: NewHttpOperationParameter; - constructor(parent: Method, param: NewHttpOperationParameter, state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Method, param: NewHttpOperationParameter, state: State, objectInitializer?: DeepPartial) { const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(param.schema, !!param.required, state); super(param.language.csharp?.name || '', typeDeclaration); this.param = param; @@ -70,7 +70,7 @@ export class NewOperationParameter extends Parameter implements EnhancedVariable /** represents a method parameter for an http operation (body) */ -export class NewOperationBodyParameter extends Parameter implements EnhancedVariable { +export class OperationBodyParameter extends Parameter implements EnhancedVariable { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string): Expression { // return this.assign(this.typeDeclaration.deserializeFromContainerMember(mediaType, container, serializedName, this)); @@ -107,9 +107,9 @@ export class NewOperationBodyParameter extends Parameter implements EnhancedVari public mediaType: KnownMediaType; public contentType: string; - public typeDeclaration: NewEnhancedTypeDeclaration; + public typeDeclaration: EnhancedTypeDeclaration; - constructor(parent: Method, name: string, description: string, schema: NewSchema, required: boolean, state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Method, name: string, description: string, schema: NewSchema, required: boolean, state: State, objectInitializer?: DeepPartial) { const typeDeclaration = state.project.modelsNamespace.NewResolveTypeDeclaration(schema, required, state.path('schema')); super(name, typeDeclaration); this.typeDeclaration = typeDeclaration; @@ -131,11 +131,11 @@ export class NewOperationBodyParameter extends Parameter implements EnhancedVari } -export class NewCallbackParameter extends Parameter { - responseType: (NewEnhancedTypeDeclaration) | null; - headerType: (NewEnhancedTypeDeclaration) | null; +export class CallbackParameter extends Parameter { + responseType: (EnhancedTypeDeclaration) | null; + headerType: (EnhancedTypeDeclaration) | null; - constructor(name: string, responseType: (NewEnhancedTypeDeclaration) | null, headerType: (NewEnhancedTypeDeclaration) | null, state: NewState, objectInitializer?: DeepPartial) { + constructor(name: string, responseType: (EnhancedTypeDeclaration) | null, headerType: (EnhancedTypeDeclaration) | null, state: State, objectInitializer?: DeepPartial) { // regular pipeline style. (callback happens after the pipline is called) if (responseType) { if (headerType) { diff --git a/powershell/llcsharp/project.ts b/powershell/llcsharp/project.ts index 20e7b6cff1..650a8f9ae2 100644 --- a/powershell/llcsharp/project.ts +++ b/powershell/llcsharp/project.ts @@ -7,14 +7,14 @@ import { Host } from '@azure-tools/autorest-extension-base'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; -import { NewState } from './generator'; -import { NewModelsNamespace } from './model/namespace'; +import { State } from './generator'; +import { ModelsNamespace } from './model/namespace'; import { ApiClass } from './operation/api-class'; import { ServiceNamespace } from './operation/namespace'; import { SupportNamespace } from './enums/namespace'; import { DeepPartial } from '@azure-tools/codegen'; -export class NewProject extends codeDomProject { +export class Project extends codeDomProject { public jsonSerialization = true; public xmlSerialization = false; @@ -22,7 +22,7 @@ export class NewProject extends codeDomProject { public emitSignals = true; public projectNamespace!: string; public overrides!: Dictionary; - protected state!: NewState; + protected state!: State; apifolder!: string; runtimefolder!: string; @@ -30,7 +30,7 @@ export class NewProject extends codeDomProject { license!: string; identityCorrection!: boolean; - constructor(protected service: Host, objectInitializer?: DeepPartial) { + constructor(protected service: Host, objectInitializer?: DeepPartial) { super(); this.apply(objectInitializer); } @@ -38,7 +38,7 @@ export class NewProject extends codeDomProject { public async init(): Promise { await super.init(); - this.state = await new NewState(this.service).init(this); + this.state = await new State(this.service).init(this); this.apifolder = await this.state.getValue('api-folder', ''); this.runtimefolder = await this.state.getValue('runtime-folder', 'runtime'); this.azure = await this.state.getValue('azure', false) || await this.state.getValue('azure-arm', false); @@ -74,7 +74,7 @@ export class NewProject extends codeDomProject { this.addNamespace(this.supportNamespace); // add model classes - this.modelsNamespace = new NewModelsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); + this.modelsNamespace = new ModelsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas')); this.modelsNamespace.header = this.license; this.addNamespace(this.modelsNamespace); @@ -88,6 +88,6 @@ export class NewProject extends codeDomProject { } public serviceNamespace!: ServiceNamespace; - public modelsNamespace!: NewModelsNamespace; + public modelsNamespace!: ModelsNamespace; public supportNamespace!: SupportNamespace; } \ No newline at end of file diff --git a/powershell/llcsharp/schema/Uuid.ts b/powershell/llcsharp/schema/Uuid.ts index 55486b5ded..fd6c5fcce1 100644 --- a/powershell/llcsharp/schema/Uuid.ts +++ b/powershell/llcsharp/schema/Uuid.ts @@ -7,23 +7,8 @@ import { nameof } from '@azure-tools/codegen'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { StringSchema } from '@azure-tools/codemodel'; -import { String, NewString } from './string'; +import { NewString } from './string'; -export class Uuid extends String { - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } - - get declaration(): string { - return 'string'; - } - public validatePresence(eventListener: Variable, property: Variable): string { - return this.isRequired ? `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim() : ''; - } - validateValue(eventListener: Variable, property: Variable): string { - return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$");`; - } -} export class NewUuid extends NewString { constructor(schema: StringSchema, isRequired: boolean) { diff --git a/powershell/llcsharp/schema/array.ts b/powershell/llcsharp/schema/array.ts index 16794ca177..0974b2c8c7 100644 --- a/powershell/llcsharp/schema/array.ts +++ b/powershell/llcsharp/schema/array.ts @@ -19,264 +19,16 @@ import { Schema as NewSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from '../schema/primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; -export class ArrayOf implements EnhancedTypeDeclaration { +export class NewArrayOf implements EnhancedTypeDeclaration { public isXmlAttribute = false; public isNullable = true; get defaultOfType() { return toExpression('null /* arrayOf */'); } - constructor(public schema: Schema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { - } - - - protected get isWrapped(): boolean { - return this.schema.xml && this.schema.xml.wrapped || false; - } - - protected get wrapperName(): string | undefined { - return this.schema.xml && this.isWrapped ? this.schema.xml.name : undefined; - } - - protected get serializedName(): string | undefined { - if (this.schema instanceof NewSchema) { - return this.schema.serialization?.xml ? this.schema.serialization.xml.name : undefined; - } else { - return this.schema.xml ? this.schema.xml.name : undefined; - } - - } - get elementTypeDeclaration(): string { - return this.elementType.declaration; - } - - get declaration(): string { - return `${this.elementType.declaration}[]`; - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get convertObjectMethod() { - try { - const v = pushTempVar(); - const i = pushTempVar(); - // return `${v} => ${v} is string || !(${v} is global::System.Collections.IEnumerable) ? new ${this.declaration} { ${this.elementType.convertObjectMethod}(${v}) } : System.Linq.Enumerable.ToArray( System.Linq.Enumerable.Select( System.Linq.Enumerable.OfType((global::System.Collections.IEnumerable)${v}), ${this.elementType.convertObjectMethod}))` - return `${v} => TypeConverterExtensions.SelectToArray<${this.elementTypeDeclaration}>(${v}, ${this.elementType.convertObjectMethod})`; - } finally { - popTempVar(); - popTempVar(); - } - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // json array - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonArray}>("${serializedName}"), out var ${tmp}) ? ${this.deserializeFromNode(mediaType, tmp, toExpression('null'))} : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - if (this.isWrapped) { - // wrapped xml arrays will have a container around them. - return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}?.Element("${this.serializedName || serializedName}")`, defaultValue)}`); - } else { - // whereas non-wrapped will have all the elements in the container directly. - return toExpression(`${this.deserializeFromNode(mediaType, `${valueOf(container)}`, defaultValue)}`); - } - } - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - const each = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp} , (${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}) ) )`; - - const deser = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(tmp, `(${each})=>(${this.elementType.declaration}) (${this.elementType.deserializeFromNode(mediaType, each, this.elementType.defaultOfType)}`)); - - return toExpression(`If( ${valueOf(node)} as ${ClientRuntime.JsonArray}, out var ${tmp}) ? ${System.Func(this).new(`()=> ${valueOf(deser)} )`)}() : ${defaultValue}`); - } - case KnownMediaType.Xml: { - // XElement should be a container of items, right? - // if the reference doesn't define an XML schema then use its default name - //const defaultName = this.elementType.schema.details.csharp.name; - //const deser = `System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select( ${tmp}.Elements("${this.elementType.schema.xml ? this.elementType.schema.xml.name || defaultName : defaultName}"), (${each})=> ${this.elementType.deserializeFromNode(mediaType, each, toExpression('null'))} ) )`; - - //return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? new System.Func<${this.elementType.declaration}[]>(()=> ${deser} )() : ${defaultValue}`); - } - } - } finally { - popTempVar(); - popTempVar(); - } - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonArray.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - } - return undefined; - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Xml: - case KnownMediaType.Json: { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - - try { - const each = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.Json: { - const serArray = `global::System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}))`; - return toExpression(`null != ${value} ? new ${ClientRuntime.XNodeArray}(${serArray}) : null`); - } - - case KnownMediaType.Xml: { - if (this.isWrapped) { - const name = this.elementType.schema.xml ? this.elementType.schema.xml.name || serializedName : serializedName; - return toExpression(`null != ${value} ? global::new System.Xml.Linq.XElement("${name}", global::System.Linq.Enumerable.ToArray(global::System.Linq.Enumerable.Select(${value}, (${each}) => ${this.elementType.serializeToNode(mediaType, each, name, mode)}))`); - } else { - throw new Error('Can\'t set an Xml Array to the document without wrapping it.'); - } - } - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - return toExpression(`(null != ${value} && ${value}.Length > 0 ? "${value}=" + ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current, each) => current + "," + ( ${this.encode}(each?.ToString()??${System.String.Empty}) ))) : ${System.String.Empty})`); - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(`(null != ${value} ? ${this.encode}(global::System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - try { - const each = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - return System.Net.Http.StringContent.new( - `${(this.serializeToNode(mediaType, value, '', mode))}`, - System.Text.Encoding.UTF8); - } - case KnownMediaType.Xml: { - // if the reference doesn't define an XML schema then use its default name - const defaultName = this.elementType.schema.details.csharp.name; - return System.Net.Http.StringContent.new(Ternery( - IsNotNull(value), - `${this.serializeToNode(mediaType, value, this.schema.xml ? this.schema.xml.name || defaultName : defaultName, mode)}).ToString()`, - System.String.Empty - ), System.Text.Encoding.UTF8); - } - - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(`(null != ${value} ? ${this.encode}(System.Linq.Enumerable.Aggregate(${value}, (current,each)=> current + "," + ${this.elementType.serializeToNode(mediaType, 'each', '', mode)})) : ${System.String.Empty})`); - } - - } finally { - popTempVar(); - } - - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - try { - const each = pushTempVar(); - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const $this = this; - return If(`null != ${value}`, function* () { - const t = new LocalVariable(tmp, dotnet.Var, { initializer: `new ${ClientRuntime.XNodeArray}()` }); - yield t.declarationStatement; - yield ForEach(each, toExpression(value), `AddIf(${$this.elementType.serializeToNode(mediaType, each, '', mode)} ,${tmp}.Add);`); - yield `${container}.Add("${serializedName}",${tmp});`; - }); - } - case KnownMediaType.Xml: - if (this.isWrapped) { - return `AddIf( ${System.Xml.Linq.XElement.new('"{this.serializedName || serializedName}"', `${this.serializeToNode(mediaType, value, this.elementType.schema.xml ? this.elementType.schema.xml.name || '!!!' : serializedName, mode)}):null`)}, ${container}.Add); `; - } else { - return If(`null != ${value}`, ForEach(each, toExpression(value), `AddIf(${this.elementType.serializeToNode(mediaType, each, serializedName, mode)}, ${container}.Add);`)); - } - } - } finally { - popTempVar(); - popTempVar(); - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `; - } - return ''; - } - validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - // check if the underlyingType has validation. - if (!this.elementType.validateValue(eventListener, new LocalVariable(`${property} [{ __i }]`, dotnet.Var))) { - return ''; - } - - return ` - if (${ property} != null ) { - for (int __i = 0; __i < ${ property}.Length; __i++) { - ${ this.elementType.validateValue(eventListener, new LocalVariable(`${property}[__i]`, dotnet.Var))} - } - } - `.trim(); - } -} - -export class NewArrayOf implements NewEnhancedTypeDeclaration { - public isXmlAttribute = false; - public isNullable = true; - get defaultOfType() { - return toExpression('null /* arrayOf */'); - } - - constructor(public schema: NewSchema, public isRequired: boolean, public elementType: NewEnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { + constructor(public schema: NewSchema, public isRequired: boolean, public elementType: EnhancedTypeDeclaration, protected minItems: number | undefined, protected maxItems: number | undefined, protected unique: boolean | undefined) { } diff --git a/powershell/llcsharp/schema/binary.ts b/powershell/llcsharp/schema/binary.ts index da9c9a0bf8..664c42ef15 100644 --- a/powershell/llcsharp/schema/binary.ts +++ b/powershell/llcsharp/schema/binary.ts @@ -10,85 +10,11 @@ import { Expression, ExpressionOrLiteral, toExpression } from '@azure-tools/code import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { BinarySchema } from '@azure-tools/codemodel'; -export class Binary implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - constructor(public schema: Schema, public isRequired: boolean) { - } - - get convertObjectMethod() { - return 'i=>i'; - } - public isNullable = true; - - get defaultOfType() { - return toExpression('null /* binary type */'); - } - - get declaration(): string { - return System.IO.Stream.declaration; - } - - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - if (mediaType === KnownMediaType.Stream) { - // dunno. - } - if (mediaType === KnownMediaType.Json) { - return toExpression('null /* no need to deserialize a stream here */ '); - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return undefined; - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`${valueOf(content)}.Content.ReadAsStreamAsync()`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - if (mediaType === KnownMediaType.Stream) { - return toExpression(System.Net.Http.StreamContent.new(value)); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - if (mediaType === KnownMediaType.Json) { - return `/* shouldn't need to serialize binary for a ${mediaType} */`; - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - public validatePresence(eventListener: Variable, property: Variable): string { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - return ''; - } -} -export class NewBinary implements NewEnhancedTypeDeclaration { +export class NewBinary implements EnhancedTypeDeclaration { public isXmlAttribute = false; constructor(public schema: BinarySchema, public isRequired: boolean) { } diff --git a/powershell/llcsharp/schema/boolean.ts b/powershell/llcsharp/schema/boolean.ts index 8942f25e50..a2f259f46c 100644 --- a/powershell/llcsharp/schema/boolean.ts +++ b/powershell/llcsharp/schema/boolean.ts @@ -7,24 +7,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, BooleanSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; - -export class Boolean extends Primitive { - isXmlAttribute = false; - jsonType = ClientRuntime.JsonBoolean; - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - - get declaration(): string { - return `bool${this.isRequired ? '' : '?'}`; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } -} +import { NewPrimitive } from './primitive'; export class NewBoolean extends NewPrimitive { isXmlAttribute = false; diff --git a/powershell/llcsharp/schema/byte-array.ts b/powershell/llcsharp/schema/byte-array.ts index 9d36914c92..1089b5ee10 100644 --- a/powershell/llcsharp/schema/byte-array.ts +++ b/powershell/llcsharp/schema/byte-array.ts @@ -12,114 +12,10 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { Schema as NewSchema, ByteArraySchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; -export class ByteArray implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - - get declaration(): string { - return 'byte[]'; - } - - get convertObjectMethod() { - return 'i => i'; - } - - public isNullable = true; - - get defaultOfType() { - return toExpression('null /* byte array */'); - } - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.Xml: { - return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}")?.Value, out var ${tmp}) ? System.Convert.FromBase64String(${tmp}.Replace("_","/").Replace("-","+").PadRight( ${tmp}.Length + ${tmp}.Length * 3 % 4, '=')) : ${defaultValue}`); - } - case KnownMediaType.Json: { - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmp}) ? System.Convert.FromBase64String( ((string)${tmp}).Replace("_","/").Replace("-","+").PadRight( ((string)${tmp}).Length + ((string)${tmp}).Length * 3 % 4, '=') ) : null`); - } - case KnownMediaType.Header: { - //const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? System.Convert.FromBase64String(${tmp}) : ${defaultValue}`); - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`${ClientRuntime.JsonString.new(`System.Convert.ToBase64String(${value})`)}`); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - try { - const b = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Xml: { - return `AddIf( null != ${value} ? ${System.Xml.Linq.XElement.new(serializedName, System.Convert.ToBase64String(value))} : null, ${container}.Add);`; - } - - case KnownMediaType.Json: { - return `AddIf( null != ${value} ? ${System.Convert.ToBase64String(value)} : null ,(v)=> ${container}.Add( "${serializedName}",v) );`; - } - - case KnownMediaType.Header: { - return If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}", ${System.Convert.ToBase64String(value)});`); - } - } - - } finally { - popTempVar(); - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - - constructor(public schema: Schema, public isRequired: boolean) { - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - public validatePresence(eventListener: Variable, property: Variable): string { - if (this.isRequired) { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - return ''; - } -} - -export class NewByteArray implements NewEnhancedTypeDeclaration { +export class NewByteArray implements EnhancedTypeDeclaration { public isXmlAttribute = false; get declaration(): string { diff --git a/powershell/llcsharp/schema/char.ts b/powershell/llcsharp/schema/char.ts index 68c576b39a..6e866a0091 100644 --- a/powershell/llcsharp/schema/char.ts +++ b/powershell/llcsharp/schema/char.ts @@ -7,40 +7,9 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, SchemaType, ChoiceSchema, ChoiceValue } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; import { length } from '@azure-tools/linq'; -export class Char extends Primitive { - public isXmlAttribute = false; - private choices?: Array; - jsonType = ClientRuntime.JsonString; - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - this.choices = length(schema.enum) > 0 ? schema.enum : undefined; - } - - get declaration(): string { - return `char${this.isRequired ? '' : ' ?'}`; - } - - get convertObjectMethod() { - return 'global::System.Convert.Char'; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateEnum(property)} - `.trim(); - } - - private validateEnum(property: Variable): string { - if (!this.choices) { - return ''; - } - return '// todo validate enum choices'; - } -} export class NewChar extends NewPrimitive { public isXmlAttribute = false; diff --git a/powershell/llcsharp/schema/date-time.ts b/powershell/llcsharp/schema/date-time.ts index f09cf4940b..6881f116b6 100644 --- a/powershell/llcsharp/schema/date-time.ts +++ b/powershell/llcsharp/schema/date-time.ts @@ -12,99 +12,8 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema, DateSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; -export class DateTime extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonString; - // public DateFormat = new StringExpression('yyyy-MM-dd'); - public DateTimeFormat = new StringExpression('yyyy\'-\'MM\'-\'dd\'T\'HH\':\'mm\':\'ss.fffffffK'); - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get declaration(): string { - return `global::System.DateTime${this.isRequired ? '' : '?'}`; - } - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; - } - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.DateTime.TryParse((string)${tmpValue}, global::System.Globalization.CultureInfo.InvariantCulture, global::System.Globalization.DateTimeStyles.AdjustToUniversal, out var ${tmpValue}Value) ? ${tmpValue}Value : ${defaultValue}`; - } - - get convertObjectMethod() { - return '(v) => v is global::System.DateTime _v ? _v : global::System.Xml.XmlConvert.ToDateTime( v.ToString() , global::System.Xml.XmlDateTimeSerializationMode.Unspecified)'; - } - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - toExpression(`(${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : - toExpression(`null != ${value} ? (${ClientRuntime.JsonNode}) new ${this.jsonType}(${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)) : null`); - - case KnownMediaType.Cookie: - case KnownMediaType.QueryParameter: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `"${serializedName}=" + ${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)` : - `(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture))` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - - case KnownMediaType.Xml: - // container : XElement - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture));`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}` : - `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}?.ToString(${this.DateTimeFormat},global::System.Globalization.CultureInfo.InvariantCulture)}"}`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - // public static string DateFormat = "yyyy-MM-dd"; - // public static string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; - // public static string DateTimeRfc1123Format = "R"; - // public static JsonString CreateDate(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateFormat, CultureInfo.InvariantCulture)) : null; - // public static JsonString CreateDateTime(DateTime? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeFormat, CultureInfo.InvariantCulture)) : null; - // public static JsonString CreateDateTimeRfc1123(DateTime ? value) => value is DateTime date ? new JsonString(date.ToString(DateTimeRfc1123Format, CultureInfo.InvariantCulture)) : null; - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } -} export class NewDateTime extends NewPrimitive { public isXmlAttribute = false; @@ -198,12 +107,7 @@ export class NewDateTime extends NewPrimitive { } } -export class DateTime1123 extends DateTime { - public DateTimeFormat = new StringExpression('R'); - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } -} + export class NewDateTime1123 extends NewDateTime { public DateTimeFormat = new StringExpression('R'); @@ -212,84 +116,6 @@ export class NewDateTime1123 extends NewDateTime { } } -export class UnixTime extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonNumber; - - private EpochDate = System.DateTime.new('1970', '1', '1', '0', '0', '0', System.DateTimeKind.Utc); - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; - } - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `long.TryParse((string)${tmpValue}, out var ${tmpValue}Value) ? ${this.EpochDate}.AddSeconds(${tmpValue}Value) : ${defaultValue}`; - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`).Cast(ClientRuntime.JsonNode) : - Ternery(IsNotNull(value), this.jsonType.new(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds)??0)`).Cast(ClientRuntime.JsonNode), dotnet.Null); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); - } - - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `(${value}.ToString())` : - `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - _serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - return super.serializeToNode(mediaType, new LiteralExpression(`((${this.longType})(${value}${this.q}.Subtract(${valueOf(this.EpochDate)}).TotalSeconds))`), serializedName, mode); - } - - get q(): string { - return this.isRequired ? '' : '?'; - } - - get longType(): string { - return this.isRequired ? 'long' : 'long?'; - } - - - constructor(schema: Schema, public isRequired: boolean) { - super(schema); - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - - get declaration(): string { - return `global::System.DateTime${this.isRequired ? '' : '?'}`; - } -} - export class NewUnixTime extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/date.ts b/powershell/llcsharp/schema/date.ts index 62de87bcdf..ddd1695954 100644 --- a/powershell/llcsharp/schema/date.ts +++ b/powershell/llcsharp/schema/date.ts @@ -6,14 +6,8 @@ import { StringExpression } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { DateSchema } from '@azure-tools/codemodel'; -import { DateTime, NewDateTime } from './date-time'; +import { NewDateTime } from './date-time'; -export class Date extends DateTime { - public DateTimeFormat = new StringExpression('yyyy-MM-dd'); - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } -} export class NewDate extends NewDateTime { public DateTimeFormat = new StringExpression('yyyy-MM-dd'); diff --git a/powershell/llcsharp/schema/duration.ts b/powershell/llcsharp/schema/duration.ts index 1203f8fb81..bfa0f4e707 100644 --- a/powershell/llcsharp/schema/duration.ts +++ b/powershell/llcsharp/schema/duration.ts @@ -9,67 +9,9 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { Schema as NewSchema, DurationSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; import { ClientRuntime } from '../clientruntime'; -export class Duration extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonString; - - constructor(public schema: Schema, public isRequired: boolean) { - super(schema); - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get declaration(): string { - return `global::System.TimeSpan${this.isRequired ? '' : '?'}`; - } - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `global::System.Xml.XmlConvert.ToTimeSpan( ${tmpValue} )`; - } - - get convertObjectMethod() { - return '(v) => v is global::System.TimeSpan _v ? _v : global::System.Xml.XmlConvert.ToTimeSpan( v.ToString() )'; - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - if (!this.isRequired) { - return toExpression(`(null != ${value} ? ${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}: null)`).Cast(ClientRuntime.JsonNode); - } - return toExpression(`${ClientRuntime.JsonString.new(`global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})`)}`).Cast(ClientRuntime.JsonNode); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value}))`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(global::System.Xml.XmlConvert.ToString((global::System.TimeSpan)${value})))`); - } - } - return toExpression(`/* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - validateValue(eventListener: Variable, property: Variable): string { - return ''; - } - public validatePresence(eventListener: Variable, property: Variable): string { - return ''; - } -} export class NewDuration extends NewPrimitive { public isXmlAttribute = false; diff --git a/powershell/llcsharp/schema/enum.ts b/powershell/llcsharp/schema/enum.ts index bf80b84f77..1ae5ceb938 100644 --- a/powershell/llcsharp/schema/enum.ts +++ b/powershell/llcsharp/schema/enum.ts @@ -5,31 +5,9 @@ import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -import { String, NewString } from './string'; +import { NewString } from './string'; import { dotnet, toExpression } from '@azure-tools/codegen-csharp'; -export class EnumImplementation extends String { - public isXmlAttribute = false; - get isNullable(): boolean { - return !this.isRequired; - } - - constructor(schema: Schema, isRequired: boolean) { - super(schema, isRequired); - } - - get defaultOfType() { - return this.isRequired ? toExpression(`((${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}${this.isRequired ? '' : '?'})"")`) : dotnet.Null; - } - - get convertObjectMethod() { - return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}.CreateFrom`; - } - - - get declaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}${this.isRequired ? '' : '?'}`; } -} - export class NewEnumImplementation extends NewString { public isXmlAttribute = false; get isNullable(): boolean { diff --git a/powershell/llcsharp/schema/extended-type-declaration.ts b/powershell/llcsharp/schema/extended-type-declaration.ts index 0a0c59d327..b08fd1ab2c 100644 --- a/powershell/llcsharp/schema/extended-type-declaration.ts +++ b/powershell/llcsharp/schema/extended-type-declaration.ts @@ -12,55 +12,8 @@ import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; /** A TypeDeclaration that can assist in generating code for a variety of serialization, validation and other common use cases */ -export interface EnhancedTypeDeclaration extends TypeDeclaration { - /** emits an expression to deserialize a property from a member inside a container */ - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression; - - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression; - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined; - - /** emits an expression serialize this to the value required by the container */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression; - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression; - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements; - - /** defaultOfType */ - readonly defaultOfType: Expression; - - readonly convertObjectMethod: string; // "global::System.Convert.ToString"; - - /** is a value for this required */ - isRequired: boolean; - - /** when encoding as xml, is this encoded as an attribute */ - isXmlAttribute: boolean; - /** the underlying schema for this type declarartion. */ - schema: Schema; - - isNullable: boolean; - - /** emits the code required to validate that this is set to a value */ - validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements; - - /** emits the code required to validate that this has a permissable value */ - validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements; -} - -export interface NewEnhancedTypeDeclaration extends TypeDeclaration { +export interface EnhancedTypeDeclaration extends TypeDeclaration { /** emits an expression to deserialize a property from a member inside a container */ deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression; diff --git a/powershell/llcsharp/schema/integer.ts b/powershell/llcsharp/schema/integer.ts index d6673cb5de..617283a1f4 100644 --- a/powershell/llcsharp/schema/integer.ts +++ b/powershell/llcsharp/schema/integer.ts @@ -8,44 +8,9 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { NumberSchema } from '@azure-tools/codemodel'; -import { Primitive, NewPrimitive } from './primitive'; +import { NewPrimitive } from './primitive'; -export class Numeric extends Primitive { - public isXmlAttribute = false; - public jsonType = ClientRuntime.JsonNumber; - - constructor(schema: Schema, public isRequired: boolean, protected numericType: string) { - super(schema); - } - get declaration(): string { - return `${this.numericType}`; - } - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateMinimum(eventListener, property)} -${this.validateMaximum(eventListener, property)} -${this.validateExclusiveMinimum(eventListener, property)} -${this.validateExclusiveMaximum(eventListener, property)} -${this.validateMultipleOf(eventListener, property)} -`.trim(); - } - protected validateMinimum(eventListener: Variable, property: Variable): string { - return this.schema.minimum && !this.schema.exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThanOrEqual(${nameof(property.value)},${property},${this.schema.minimum});` : ''; - } - protected validateMaximum(eventListener: Variable, property: Variable): string { - return this.schema.maximum && !this.schema.exclusiveMaximum ? `await ${eventListener}.AssertIsLessThanOrEqual(${nameof(property.value)},${property},${this.schema.maximum});` : ''; - } - protected validateExclusiveMinimum(eventListener: Variable, property: Variable): string { - return this.schema.minimum && this.schema.exclusiveMinimum ? `await ${eventListener}.AssertIsGreaterThan(${nameof(property.value)},${property},${this.schema.minimum});` : ''; - } - protected validateExclusiveMaximum(eventListener: Variable, property: Variable): string { - return this.schema.maximum && this.schema.exclusiveMaximum ? `await ${eventListener}.AssertIsLessThan(${nameof(property.value)},${property},${this.schema.maximum});` : ''; - } - protected validateMultipleOf(eventListener: Variable, property: Variable): string { - return this.schema.multipleOf ? `await ${eventListener}.AssertIsMultipleOf(${nameof(property.value)},${property},${this.schema.multipleOf});` : ''; - } -} export class NewNumeric extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/object.ts b/powershell/llcsharp/schema/object.ts index bb9dce1cad..cf6a138e81 100644 --- a/powershell/llcsharp/schema/object.ts +++ b/powershell/llcsharp/schema/object.ts @@ -16,172 +16,10 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, ObjectSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; -export class ObjectImplementation implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - - get defaultOfType() { - return toExpression('null /* object */'); - } - - get isNullable(): boolean { - return true; - } - - get convertObjectMethod() { - return `${this.schema.details.csharp.fullname}TypeConverter.ConvertFrom`; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // JsonObject - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonObject}>("${serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromJson(${tmp}) : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement or XElement/XAttribute - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - // prefer specified XML name if available - return toExpression(`If( ${valueOf(container)}?.Element("${this.schema.xml ? this.schema.xml.name || serializedName : serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); - } - /** emits an expression to deserialze a container as the value itself. */ - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: { - // we're always going to go thru FromJson; it'll handle nulls and polymorphism. - return toExpression(`${this.classDeclaration}.FromJson(${node}) `); - } - case KnownMediaType.Xml: { - - return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - return toExpression(`${value}?.ToJson(null, ${mode.value})`); - } - case KnownMediaType.Xml: { - return toExpression(`${value}?.ToXml(null, ${mode.value})`); - } - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to the value required by the container */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - return System.Net.Http.StringContent.new( - Ternery( - IsNotNull(value), - `${value}.ToJson(null).ToString()`, - new StringExpression('{}')), - System.Text.Encoding.UTF8); - } - case KnownMediaType.Xml: { - return System.Net.Http.StringContent.new( - Ternery( - IsNotNull(value), - `${value}.ToXml(null).ToString()`, - System.String.Empty), - System.Text.Encoding.UTF8); - } - case KnownMediaType.Multipart: { - let contents = ''; - for (const p of values(this.schema.properties)) { - // to do -- add in a potential support for the filename too. - contents = `${contents}${EOL} bodyContent.Add( ${System.Net.Http.StreamContent.new(`${value}.${p.details.csharp.name}`)},"${p.serializedName}");`; - } - // bodyContent.Add(new _ystem.Net.Http.StreamContent(body.AudioFile), "audioFile"); - return toExpression(`new ${System.Func(System.Net.Http.MultipartFormDataContent)}(() => -{ - var bodyContent = ${System.Net.Http.MultipartFormDataContent.new()}; - ${contents} - return bodyContent; -})()`); - } - } - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - } - return undefined; - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - if (this.schema.details.csharp.hasHeaders) { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)}.ReadHeaders(_response.Headers))`); - } - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - case KnownMediaType.Xml: { - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - } - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits the code required to serialize this into a container */ - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - // const v = (value).valuePrivate || value; - switch (mediaType) { - case KnownMediaType.Json: - return `AddIf( null != ${value} ? (${ClientRuntime.JsonNode}) ${value}.ToJson(null,${mode.value}) : null, "${serializedName}" ,${container}.Add );`; - - case KnownMediaType.Xml: - // prefer specified XML name if available - return `AddIf( null != ${value} ? ${value}.ToXml(new ${System.Xml.Linq.XElement}("${this.schema.xml ? this.schema.xml.name || serializedName : serializedName}")) : null, ${container}.Add );`; - - } - return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; - } - - isRequired = false; - - constructor(public schema: Schema) { - } - - public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `.trim(); - } - public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { - return `await ${eventListener}.AssertObjectIsValid(${nameof(property.value)}, ${property}); `; - } - get declaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.interfaceName}`; } - get classDeclaration(): string { return `${this.schema.details.csharp.namespace}.${this.schema.details.csharp.name}`; } - -} - -export class NewObjectImplementation implements NewEnhancedTypeDeclaration { +export class ObjectImplementation implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/llcsharp/schema/primitive.ts b/powershell/llcsharp/schema/primitive.ts index 50c34b01c9..2264da2951 100644 --- a/powershell/llcsharp/schema/primitive.ts +++ b/powershell/llcsharp/schema/primitive.ts @@ -15,7 +15,7 @@ import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, PrimitiveSchema } from '@azure-tools/codemodel'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; let tmpVar: number | undefined; let max = 0; @@ -49,190 +49,7 @@ export function popTempVar() { } } -export abstract class Primitive implements EnhancedTypeDeclaration { - abstract isRequired: boolean; - abstract isXmlAttribute: boolean; - abstract declaration: string; - abstract jsonType: ClassType; - get isNullable(): boolean { - return !this.isRequired; - } - - get encode(): string { - return this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - get defaultOfType() { - return toExpression(`default(${this.declaration})`); - } - - get convertObjectMethod() { - const v = pushTempVar(); - const result = `(${v})=> (${this.baseType}) global::System.Convert.ChangeType(${v}, typeof(${this.baseType}))`; - popTempVar(); - - return result; - } - - constructor(public schema: Schema) { - } - /** validatePresence on primitives is generally not required; the nullability determines requiredness... */ - public validatePresence(eventListener: Variable, property: Variable): string { - return ''; - } - - abstract validateValue(eventListener: Variable, property: Variable): string; - protected get baseType(): string { - return this.declaration.replace('?', ''); - } - - protected castJsonTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `(${this.declaration})${tmpValue}`; - } - - protected castXmlTypeToPrimitive(tmpValue: string, defaultValue: string) { - return `(${this.declaration})${tmpValue}`; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // JsonObject - const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${this.jsonType}>("${serializedName}"), out var ${tmp}) ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - } - - case KnownMediaType.Xml: { - // XElement/XElement or XElement/XAttribute - const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - - return toExpression(this.isXmlAttribute ? - `If( ${valueOf(container)}?.Attribute("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : - `If( ${valueOf(container)}?.Element("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - } - - case KnownMediaType.Header: { - // HttpResponseHeaders - const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${this.baseType}.TryParse( ${tmp}, out ${this.baseType} ${tmp}Value ) ? ${tmp}Value : ${defaultValue} : ${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); - } - - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: - // node should be a json type - return toExpression(`${node} is ${this.jsonType} ${tmp} ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`); - - case KnownMediaType.Xml: - // XElement or XAttribute - return toExpression( - this.isXmlAttribute ? - `${node} is ${System.Xml.Linq.XAttribute} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` : - `${node} is ${System.Xml.Linq.XElement} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)}: ${defaultValue}`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainer doens't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - try { - const tmp = pushTempVar(); - - switch (mediaType) { - case KnownMediaType.UriParameter: { - return toExpression(`${this.baseType}.TryParse( ${valueOf(content)}, out ${this.baseType} ${tmp} ) ? ${tmp} : ${defaultValue}`); - - } - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return this.isRequired ? - this.jsonType.new(value).Cast(ClientRuntime.JsonNode) : - Ternery(IsNotNull(value), this.jsonType.new(`(${this.baseType})${value}`).Cast(ClientRuntime.JsonNode), dotnet.Null); - - case KnownMediaType.Xml: - return this.isRequired ? - toExpression(`new ${System.Xml.Linq.XElement}("${serializedName}",${value})`) : - toExpression(`null != ${value} ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value}.ToString())`); - } else { - return toExpression(`(null == ${value} ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${value}.ToString()))`); - } - - // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`); - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - return toExpression(this.isRequired ? - `(${value}.ToString())` : - `(null == ${value} ? ${System.String.Empty} : ${value}.ToString())` - ); - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - // container : JsonObject - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${valueOf(container)}.Add );`; - - case KnownMediaType.Xml: - // container : XElement - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${valueOf(container)}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value}.ToString());`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}"}`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } -} - -export abstract class NewPrimitive implements NewEnhancedTypeDeclaration { +export abstract class NewPrimitive implements EnhancedTypeDeclaration { abstract isRequired: boolean; abstract isXmlAttribute: boolean; abstract declaration: string; diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 0935d3487a..9f3353f04f 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -8,33 +8,33 @@ import { codeModelSchema, ArraySchema, UnixTimeSchema, CodeModel, Schema as NewS import { codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; -import { ArrayOf, NewArrayOf } from './array'; -import { Binary, NewBinary } from './binary'; -import { Boolean, NewBoolean } from './boolean'; -import { ByteArray, NewByteArray } from './byte-array'; -import { Char, NewChar } from './char'; -import { Date, NewDate } from './date'; -import { DateTime, DateTime1123, UnixTime, NewDateTime, NewDateTime1123, NewUnixTime } from './date-time'; -import { Duration, NewDuration } from './duration'; -import { EnumImplementation, NewEnumImplementation } from './enum'; -import { Numeric, NewNumeric } from './integer'; -import { ObjectImplementation, NewObjectImplementation } from './object'; -import { String, NewString } from './string'; -import { Uuid, NewUuid } from './Uuid'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { NewArrayOf } from './array'; +import { NewBinary } from './binary'; +import { NewBoolean } from './boolean'; +import { NewByteArray } from './byte-array'; +import { NewChar } from './char'; +import { NewDate } from './date'; +import { NewDateTime, NewDateTime1123, NewUnixTime } from './date-time'; +import { NewDuration } from './duration'; +import { NewEnumImplementation } from './enum'; +import { NewNumeric } from './integer'; +import { ObjectImplementation } from './object'; +import { NewString } from './string'; +import { NewUuid } from './Uuid'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { PwshModel } from '../../utils/PwshModel'; import { ModelState } from '../../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { schemaHasEnum } from '../validations'; -export class NewSchemaDefinitionResolver { - private readonly cache = new Map(); - private add(schema: NewSchema, value: NewEnhancedTypeDeclaration): NewEnhancedTypeDeclaration { +export class SchemaDefinitionResolver { + private readonly cache = new Map(); + private add(schema: NewSchema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration { this.cache.set(schema.language?.csharp?.fullname || '', value); return value; } - resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): NewEnhancedTypeDeclaration { + resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState): EnhancedTypeDeclaration { if (!schema) { throw new Error('SCHEMA MISSING?'); } @@ -56,7 +56,7 @@ export class NewSchemaDefinitionResolver { if (result) { return result; } - return this.add(schema, new NewObjectImplementation(schema)); + return this.add(schema, new ObjectImplementation(schema)); } case SchemaType.Time: case SchemaType.Credential: diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index a39aa57f1d..ce4adcc71b 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -14,203 +14,13 @@ import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { ChoiceSchema, Schema as NewSchema, SchemaType, SealedChoiceSchema, StringSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from './primitive'; -import { EnhancedTypeDeclaration, NewEnhancedTypeDeclaration } from './extended-type-declaration'; +import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; -/** A ETD for the c# string type. */ -export class String implements EnhancedTypeDeclaration { - public isXmlAttribute = false; - - get defaultOfType() { - return toExpression('null'); - } - get convertObjectMethod() { - return 'global::System.Convert.ToString'; - } - - get isNullable(): boolean { - return true; - } - - get encode(): string { - return this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; - } - - deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: { - // container should be a JsonObject - const tmpVar = `__${camelCase(['json', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmpVar}) ? (string)${tmpVar} : (string)${defaultValue}`); - } - case KnownMediaType.Xml: { - const xTmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; - return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}"), out var ${xTmp}) ? (string)${xTmp} : (string)${defaultValue}`); - } - case KnownMediaType.Header: { - // HttpResponseHeaders - const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; - return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${tmp} : (string)${defaultValue}`); - } - } - return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { - try { - const tmp = pushTempVar(); - switch (mediaType) { - case KnownMediaType.Json: - // node should be a JsonString - return toExpression(`${node} is ${ClientRuntime.JsonString} ${tmp} ? (${this.declaration})(${tmp}.ToString()) : ${defaultValue}`); - - case KnownMediaType.Xml: - return toExpression(`${node} is ${System.Xml.Linq.XElement} ${tmp} ? (string)${tmp} : ${defaultValue}`); - } - } finally { - popTempVar(); - } - return toExpression(`null /* deserializeFromContainer doesn't support '${mediaType}' ${__filename}*/`); - } - /** emits an expression serialize this to a HttpContent */ - serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { - return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`null != (((object)${value})?.ToString()) ? (${ClientRuntime.JsonNode}) new ${ClientRuntime.JsonString}(${value}.ToString()) : null`); - - case KnownMediaType.Xml: - return toExpression(`null != (${value}?.ToString()) ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); - - case KnownMediaType.QueryParameter: - - if (this.isRequired) { - return toExpression(`"${serializedName}=" + ${this.encode}(${value})`); - } else { - return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : "${serializedName}=" + ${this.encode}(${valueOf(value)}))`); - } - - case KnownMediaType.Cookie: - case KnownMediaType.Header: - case KnownMediaType.Text: - case KnownMediaType.UriParameter: - if (this.isRequired) { - return toExpression(`${this.encode}(${value})`); - } - return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : ${this.encode}(${value}) )`); - - } - return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); - } - - /** emits an expression to deserialize content from a string */ - deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: { - return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); - } - case KnownMediaType.Xml: { - return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); - } - case KnownMediaType.UriParameter: { - return toExpression(content); - } - } - return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); - } - - /** emits an expression to deserialize content from a content/response */ - deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { - switch (mediaType) { - case KnownMediaType.Json: - return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); - - } - return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); - } - - serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { - switch (mediaType) { - case KnownMediaType.Json: - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${container}.Add );`; - - case KnownMediaType.Xml: - return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${container}.Add );`; - - case KnownMediaType.Header: - // container : HttpRequestHeaders - return this.isRequired ? - `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : - If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value});`); - - case KnownMediaType.QueryParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `${serializedName}={${value}.ToString()}` : - `{null == ${value} ? ${System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`; - - case KnownMediaType.UriParameter: - // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter - return this.isRequired ? - `(${serializedName}={${value}.ToString()})` : - `(null == ${value} ? ${System.String.Empty}: $"${serializedName}={${value}.ToString()}")`; - } - return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); - } - - constructor(public schema: Schema, public isRequired: boolean) { - } - - get declaration(): string { - return 'string'; - } - - validateValue(eventListener: Variable, property: Variable): string { - return ` -${this.validateMinLength(eventListener, property)} -${this.validateMaxLength(eventListener, property)} -${this.validateRegex(eventListener, property)} -${this.validateEnum(eventListener, property)} - `.trim(); - - } - - public validatePresence(eventListener: Variable, property: Variable): string { - return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); - } - - private validateMinLength(eventListener: Variable, property: Variable): string { - if (!this.schema.minLength) { - return ''; - } - return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${this.schema.minLength});`; - } - private validateMaxLength(eventListener: Variable, property: Variable): string { - if (!this.schema.maxLength) { - return ''; - } - return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${this.schema.maxLength});`; - } - private validateRegex(eventListener: Variable, property: Variable): string { - if (!this.schema.pattern) { - return ''; - } - return `await ${eventListener}.AssertRegEx(${nameof(property.value)},${property},@"${this.schema.pattern}");`; - } - private validateEnum(eventListener: Variable, property: Variable): string { - if (!this.schema.enum || length(this.schema.enum) === 0) { - return ''; - } - return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${this.schema.enum.joinWith((v) => `@"${v}"`)});`; - } -} /** A ETD for the c# string type. */ -export class NewString implements NewEnhancedTypeDeclaration { +export class NewString implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/llcsharp/validations.ts b/powershell/llcsharp/validations.ts index 9300bce754..0a86cb8934 100644 --- a/powershell/llcsharp/validations.ts +++ b/powershell/llcsharp/validations.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { JsonType, Schema } from '@azure-tools/codemodel-v3'; -import { NewState } from './generator'; +import { State } from './generator'; import * as message from './messages'; import { length } from '@azure-tools/linq'; -export function objectWithFormat(schema: Schema, state: NewState): boolean { +export function objectWithFormat(schema: Schema, state: State): boolean { if (schema.type === JsonType.Object && schema.format) { state.error(`Schema is declared 'object' but has a format: '${schema.format}'`, message.ObjectShouldNotHaveFormat); return true; @@ -16,7 +16,7 @@ export function objectWithFormat(schema: Schema, state: NewState): boolean { return false; } -export function schemaHasEnum(schema: Schema, state: NewState): boolean { +export function schemaHasEnum(schema: Schema, state: State): boolean { if (length(schema.enum) > 0) { state.error(`Schema with type:'${schema.type} and 'format:'${schema.format}' does not support 'enum' value restrictions.`, message.DoesNotSupportEnum); return true; @@ -24,7 +24,7 @@ export function schemaHasEnum(schema: Schema, state: NewState): boolean { return false; } -export function hasXmsEnum(schema: Schema, state: NewState): boolean { +export function hasXmsEnum(schema: Schema, state: State): boolean { if (length(schema.enum) > 0) { if (schema.extensions && schema.extensions['x-ms-enum']) { state.error(`Schema with type:'${schema.type} and 'format:'${schema.format}' does not support 'x-ms-enum' generation `, message.SchemaDoeNotSupportXMSEnum); @@ -34,7 +34,7 @@ export function hasXmsEnum(schema: Schema, state: NewState): boolean { return false; } -export function arrayMissingItems(schema: Schema, state: NewState): boolean { +export function arrayMissingItems(schema: Schema, state: State): boolean { if (schema.type === JsonType.Array && !schema.items) { state.error('Array schema missing items type', message.ArrayMissingItems); return true; diff --git a/powershell/models/model-extensions.ts b/powershell/models/model-extensions.ts index 9fbd4c337d..8024ec3f3a 100644 --- a/powershell/models/model-extensions.ts +++ b/powershell/models/model-extensions.ts @@ -5,8 +5,8 @@ import { DictionarySchema, ObjectSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel'; import { items, values, keys, Dictionary, length } from '@azure-tools/linq'; import { Catch, Try, Else, ElseIf, If, Interface, Attribute, Parameter, Modifier, dotnet, Class, LambdaMethod, LiteralExpression, Method, Namespace, System, Return, LocalVariable, Constructor, IsAssignableFrom, ImportDirective, Property, Access, InterfaceProperty } from '@azure-tools/codegen-csharp'; -import { Schema, ClientRuntime, ObjectImplementation, NewObjectImplementation, NewSchemaDefinitionResolver, NewDeserializerPartialClass } from '../llcsharp/exports'; -import { NewState } from '../internal/state'; +import { Schema, ClientRuntime, ObjectImplementation, SchemaDefinitionResolver, DeserializerPartialClass } from '../llcsharp/exports'; +import { State } from '../internal/state'; import { PSObject, PSTypeConverter, TypeConverterAttribute } from '../internal/powershell-declarations'; import { join } from 'path'; import { DeepPartial } from '@azure-tools/codegen'; @@ -16,14 +16,14 @@ class ApiVersionModelExtensionsNamespace extends Namespace { public get outputFolder(): string { return `${this.baseFolder}/${this.apiVersion.replace(/.*\./g, '')}`; } - constructor(private baseFolder: string, private readonly apiVersion: string, objectInitializer?: DeepPartial) { + constructor(private baseFolder: string, private readonly apiVersion: string, objectInitializer?: DeepPartial) { super(apiVersion); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); } } -export class NewModelExtensionsNamespace extends Namespace { +export class ModelExtensionsNamespace extends Namespace { CreateReferenceType(): Class { const rt = new Class(this, 'ReferenceType'); rt.add(new Property('Id', dotnet.String, { setAccess: Access.Internal })); @@ -34,9 +34,9 @@ export class NewModelExtensionsNamespace extends Namespace { public get outputFolder(): string { return join(this.state.project.apiFolder, 'Models'); } - resolver = new NewSchemaDefinitionResolver(); + resolver = new SchemaDefinitionResolver(); - constructor(parent: Namespace, private schemas: Dictionary>, private state: NewState, objectInitializer?: DeepPartial) { + constructor(parent: Namespace, private schemas: Dictionary>, private state: State, objectInitializer?: DeepPartial) { super('Models', parent); this.apply(objectInitializer); this.add(new ImportDirective(`${ClientRuntime.name}.PowerShell`)); @@ -53,7 +53,7 @@ export class NewModelExtensionsNamespace extends Namespace { } const td = this.resolver.resolveTypeDeclaration(schema, true, state); - if (td instanceof NewObjectImplementation) { + if (td instanceof ObjectImplementation) { // it's a class object. const className = td.schema.language.csharp?.name || ''; @@ -118,8 +118,8 @@ export class NewModelExtensionsNamespace extends Namespace { returnsDescription: 'a containing this model serialized to JSON text.' })); - const hashDeseralizer = new NewDeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); - const psDeseralizer = new NewDeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); + const hashDeseralizer = new DeserializerPartialClass(model, modelInterface, System.Collections.IDictionary, 'Dictionary', schema, resolver).init(); + const psDeseralizer = new DeserializerPartialClass(model, modelInterface, PSObject, 'PSObject', schema, resolver).init(); // + static FromJsonString(string json); // + string ToJsonString() diff --git a/powershell/module/module-class.ts b/powershell/module/module-class.ts index b7883aae6d..40dbf645bb 100644 --- a/powershell/module/module-class.ts +++ b/powershell/module/module-class.ts @@ -6,7 +6,7 @@ import { Access, Alias, Class, ClassType, Constructor, dotnet, Field, If, LambdaMethod, LambdaProperty, LazyProperty, LiteralExpression, LocalVariable, MemberVariable, Method, Modifier, Namespace, Parameter, ParameterModifier, PartialMethod, Property, Return, Statements, StringExpression, System, TypeDeclaration, Using, valueOf, Variable } from '@azure-tools/codegen-csharp'; import { InvocationInfo, PSCredential, IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType, } from '../internal/powershell-declarations'; -import { NewState } from '../internal/state'; +import { State } from '../internal/state'; import { ClientRuntime } from '../llcsharp/exports'; import { DeepPartial } from '@azure-tools/codegen'; @@ -71,7 +71,7 @@ export class NewModuleClass extends Class { fHandler = this.add(new Field('_handler', System.Net.Http.HttpClientHandler, { initialValue: System.Net.Http.HttpClientHandler.new() })); fWebProxy = this.add(new Field('_webProxy', System.Net.WebProxy, { initialValue: System.Net.WebProxy.new() })); - constructor(namespace: Namespace, private readonly state: NewState, objectInitializer?: DeepPartial) { + constructor(namespace: Namespace, private readonly state: State, objectInitializer?: DeepPartial) { super(namespace, 'Module'); this.apply(objectInitializer); this.partial = true; diff --git a/powershell/module/module-namespace.ts b/powershell/module/module-namespace.ts index 7a566dac6d..f6afc90087 100644 --- a/powershell/module/module-namespace.ts +++ b/powershell/module/module-namespace.ts @@ -4,18 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../llcsharp/exports'; -import { NewState } from '../internal/state'; +import { State } from '../internal/state'; import { NewModuleClass } from './module-class'; import { DeepPartial } from '@azure-tools/codegen'; -export class NewModuleNamespace extends Namespace { +export class ModuleNamespace extends Namespace { public moduleClass: NewModuleClass; public get outputFolder(): string { return this.state.project.moduleFolder; } - constructor(public state: NewState, objectInitializer?: DeepPartial) { + constructor(public state: State, objectInitializer?: DeepPartial) { super(state.model.language.csharp?.namespace || 'INVALID.NAMESPACE', state.project); this.apply(objectInitializer); this.add(new ImportDirective(`static ${ClientRuntime.Extensions}`)); diff --git a/powershell/plugins/cs-namer-v2.ts b/powershell/plugins/cs-namer-v2.ts index dea8d9e06f..be6a2e70d7 100644 --- a/powershell/plugins/cs-namer-v2.ts +++ b/powershell/plugins/cs-namer-v2.ts @@ -10,7 +10,7 @@ import { System } from '@azure-tools/codegen-csharp'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { SchemaDetails } from '../llcsharp/code-model'; -import { NewSchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; +import { SchemaDefinitionResolver } from '../llcsharp/schema/schema-resolver'; import { PwshModel } from '../utils/PwshModel'; import { ModelState } from '../utils/model-state'; import { SchemaDetails as NewSchemaDetails } from '../utils/schema'; @@ -159,7 +159,7 @@ function setSchemaNames(schemaGroups: Dictionary>, azure: boolean, } -async function setOperationNames(state: State, resolver: NewSchemaDefinitionResolver) { +async function setOperationNames(state: State, resolver: SchemaDefinitionResolver) { // keep a list of operation names that we've assigned. const operationNames = new Set(); for (const operationGroup of values(state.model.operationGroups)) { @@ -230,7 +230,7 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso } async function nameStuffRight(state: State): Promise { - const resolver = new NewSchemaDefinitionResolver(); + const resolver = new SchemaDefinitionResolver(); const model = state.model; // set the namespace for the service diff --git a/powershell/plugins/llcsharp-v2.ts b/powershell/plugins/llcsharp-v2.ts index 115f267f8c..c90a8a2c61 100644 --- a/powershell/plugins/llcsharp-v2.ts +++ b/powershell/plugins/llcsharp-v2.ts @@ -7,7 +7,7 @@ import { codeModelSchema } from '@azure-tools/codemodel'; import { applyOverrides, copyResources, deserialize, serialize, } from '@azure-tools/codegen'; import { join } from 'path'; import { Model } from '../llcsharp/code-model'; -import { NewProject } from '../llcsharp/project'; +import { Project } from '../llcsharp/project'; import { PwshModel } from '../utils/PwshModel'; import { Dictionary } from '@azure-tools/linq'; @@ -15,7 +15,7 @@ const resources = `${__dirname}/../../resources`; export async function llcsharpV2(service: Host) { try { - const project = await new NewProject(service).init(); + const project = await new Project(service).init(); await project.writeFiles(async (fname, content) => service.WriteFile(join(project.apifolder, fname), applyOverrides(content, project.overrides), undefined, 'source-file-csharp')); diff --git a/powershell/plugins/powershell-v2.ts b/powershell/plugins/powershell-v2.ts index 6d89881341..580fc18373 100644 --- a/powershell/plugins/powershell-v2.ts +++ b/powershell/plugins/powershell-v2.ts @@ -7,7 +7,7 @@ import { deserialize, applyOverrides, copyResources, copyBinaryResources, safeEval } from '@azure-tools/codegen'; import { Host } from '@azure-tools/autorest-extension-base'; import { join } from 'path'; -import { NewProject } from '../internal/project'; +import { Project } from '../internal/project'; import { generatePsm1 } from '../generators/psm1'; import { generateCsproj } from '../generators/csproj'; import { generatePsm1Custom } from '../generators/psm1.custom'; @@ -22,7 +22,7 @@ const sourceFileCSharp = 'source-file-csharp'; const resources = `${__dirname}/../../resources`; -async function copyRequiredFiles(project: NewProject) { +async function copyRequiredFiles(project: Project) { const transformOutput = async (input: string) => { return await project.state.resolveVariables(input); }; // Project assets @@ -48,7 +48,7 @@ export async function powershellV2(service: Host) { const debug = await service.GetValue('debug') || false; try { - const project = await new NewProject(service).init(); + const project = await new Project(service).init(); await project.writeFiles(async (filename, content) => project.state.writeFile(filename, applyOverrides(content, project.overrides), undefined, sourceFileCSharp)); diff --git a/powershell/utils/schema.ts b/powershell/utils/schema.ts index b5ccf61d85..77a0ac62ec 100644 --- a/powershell/utils/schema.ts +++ b/powershell/utils/schema.ts @@ -9,9 +9,9 @@ import { DeepPartial, } from '@azure-tools/codegen'; import { Dictionary, values } from '@azure-tools/linq'; import { uid } from './uid'; import { Schema, ObjectSchema, Property, SchemaType, isObjectSchema } from '@azure-tools/codemodel'; -import { NewEnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; -import { NewModelClass } from '../llcsharp/model/model-class'; -import { NewModelInterface } from '../llcsharp/model/interface'; +import { EnhancedTypeDeclaration } from '../llcsharp/schema/extended-type-declaration'; +import { ModelClass } from '../llcsharp/model/model-class'; +import { ModelInterface } from '../llcsharp/model/interface'; export interface PropertyDetails extends ImplementationDetails { required: boolean; @@ -97,10 +97,10 @@ export interface SchemaDetails extends ImplementationDetails { suppressFormat?: boolean; - typeDeclaration?: NewEnhancedTypeDeclaration; - classImplementation?: NewModelClass; - interfaceImplementation?: NewModelInterface; - internalInterfaceImplementation?: NewModelInterface; + typeDeclaration?: EnhancedTypeDeclaration; + classImplementation?: ModelClass; + interfaceImplementation?: ModelInterface; + internalInterfaceImplementation?: ModelInterface; interfaceName?: string; internalInterfaceName?: string; fullInternalInterfaceName?: string; From 00ef2419b6d00fbc7d3927df713d15750e2ec4c9 Mon Sep 17 00:00:00 2001 From: derek Date: Fri, 16 Oct 2020 12:29:34 +0800 Subject: [PATCH 5/5] Remove New from types --- powershell/cmdlets/class.ts | 18 ++--- powershell/internal/project.ts | 4 +- powershell/llcsharp/enums/enum.ts | 6 +- powershell/llcsharp/exports.ts | 2 +- powershell/llcsharp/model/namespace.ts | 4 +- powershell/llcsharp/schema/Uuid.ts | 4 +- powershell/llcsharp/schema/array.ts | 2 +- powershell/llcsharp/schema/binary.ts | 2 +- powershell/llcsharp/schema/boolean.ts | 2 +- powershell/llcsharp/schema/byte-array.ts | 2 +- powershell/llcsharp/schema/char.ts | 2 +- powershell/llcsharp/schema/date-time.ts | 6 +- powershell/llcsharp/schema/date.ts | 4 +- powershell/llcsharp/schema/duration.ts | 2 +- powershell/llcsharp/schema/enum.ts | 4 +- powershell/llcsharp/schema/integer.ts | 2 +- powershell/llcsharp/schema/schema-resolver.ts | 68 +++++++++---------- powershell/llcsharp/schema/string.ts | 2 +- powershell/plugins/plugin-tweak-model.ts | 2 +- 19 files changed, 69 insertions(+), 69 deletions(-) diff --git a/powershell/cmdlets/class.ts b/powershell/cmdlets/class.ts index ac300361fe..5ede09c12b 100644 --- a/powershell/cmdlets/class.ts +++ b/powershell/cmdlets/class.ts @@ -13,7 +13,7 @@ import { Access, Attribute, BackedProperty, Catch, Class, ClassType, Constructor, dotnet, Else, Expression, Finally, ForEach, If, LambdaProperty, LiteralExpression, LocalVariable, Method, Modifier, Namespace, OneOrMoreStatements, Parameter, Property, Return, Statements, BlockStatement, StringExpression, Switch, System, TerminalCase, toExpression, Try, Using, valueOf, Field, IsNull, Or, ExpressionOrLiteral, TerminalDefaultCase, xmlize, TypeDeclaration, And, IsNotNull, PartialMethod, Case } from '@azure-tools/codegen-csharp'; -import { ClientRuntime, EventListener, Schema, NewArrayOf, NewEnumImplementation } from '../llcsharp/exports'; +import { ClientRuntime, EventListener, Schema, ArrayOf, EnumImplementation } from '../llcsharp/exports'; import { Alias, ArgumentCompleterAttribute, AsyncCommandRuntime, AsyncJob, CmdletAttribute, ErrorCategory, ErrorRecord, Events, InvocationInfo, OutputTypeAttribute, ParameterAttribute, PSCmdlet, PSCredential, SwitchParameter, ValidateNotNull, verbEnum, GeneratedAttribute, DescriptionAttribute, CategoryAttribute, ParameterCategory, ProfileAttribute, PSObject, InternalExportAttribute, ExportAsAttribute, DefaultRunspace, RunspaceFactory, AllowEmptyCollectionAttribute } from '../internal/powershell-declarations'; import { State } from '../internal/state'; import { Channel } from '@azure-tools/autorest-extension-base'; @@ -1266,10 +1266,10 @@ export class CmdletClass extends Class { addDefaultInfo(cmdletParameter, vParam); } - const isEnum = propertyType instanceof NewEnumImplementation;; - const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const isEnum = propertyType instanceof EnumImplementation;; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { - cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + cmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } // add aliases if there is any if (length(vParam.alias) > 0) { @@ -1411,10 +1411,10 @@ export class CmdletClass extends Class { // regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${this.declaration})`] })); } - const isEnum = propertyType instanceof NewEnumImplementation; - const hasEnum = propertyType instanceof NewArrayOf && propertyType.elementType instanceof NewEnumImplementation; + const isEnum = propertyType instanceof EnumImplementation; + const hasEnum = propertyType instanceof ArrayOf && propertyType.elementType instanceof EnumImplementation; if (isEnum || hasEnum) { - regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); + regularCmdletParameter.add(new Attribute(ArgumentCompleterAttribute, { parameters: [`typeof(${hasEnum ? (propertyType).elementType.declaration : propertyType.declaration})`] })); } } const ifmatch = this.properties.find((v) => v.name.toLowerCase() === 'ifmatch'); @@ -1478,7 +1478,7 @@ export class CmdletClass extends Class { } else { let type = ''; - if (typeDeclaration instanceof NewArrayOf) { + if (typeDeclaration instanceof ArrayOf) { type = typeDeclaration.elementTypeDeclaration; } else if (pageableInfo && pageableInfo.responseType === 'pageable') { if (typeDeclaration === undefined || (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName) === undefined) { @@ -1488,7 +1488,7 @@ export class CmdletClass extends Class { } const nestedSchema = (typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName)?.schema; const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state); - type = (nestedTypeDeclaration).elementTypeDeclaration; + type = (nestedTypeDeclaration).elementTypeDeclaration; } else { type = typeDeclaration.declaration; } diff --git a/powershell/internal/project.ts b/powershell/internal/project.ts index e8a730dcff..ca37f32a5a 100644 --- a/powershell/internal/project.ts +++ b/powershell/internal/project.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Dictionary } from '@azure-tools/linq'; -import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, NewBoolean, SchemaDefinitionResolver } from '../llcsharp/exports'; +import { SchemaDetails, LanguageDetails, EnhancedTypeDeclaration, Boolean, SchemaDefinitionResolver } from '../llcsharp/exports'; import { State } from './state'; import { Project as codeDomProject } from '@azure-tools/codegen-csharp'; import { EnumNamespace } from '../enums/namespace'; @@ -35,7 +35,7 @@ export interface Metadata { -export class NewPSSwitch extends NewBoolean { +export class NewPSSwitch extends Boolean { get declaration(): string { return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`; } diff --git a/powershell/llcsharp/enums/enum.ts b/powershell/llcsharp/enums/enum.ts index 6287f37edc..c7de14f5ec 100644 --- a/powershell/llcsharp/enums/enum.ts +++ b/powershell/llcsharp/enums/enum.ts @@ -20,7 +20,7 @@ import { Property } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Struct } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; -import { NewEnumImplementation } from '../schema/enum'; +import { EnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { State } from '../generator'; import { DeepPartial } from '@azure-tools/codegen'; @@ -28,7 +28,7 @@ import { DeepPartial } from '@azure-tools/codegen'; import { Schema as NewSchema } from '@azure-tools/codemodel'; export class EnumClass extends Struct implements EnhancedTypeDeclaration { - implementation: NewEnumImplementation; + implementation: EnumImplementation; get schema(): NewSchema { return this.implementation.schema; } @@ -78,7 +78,7 @@ export class EnumClass extends Struct implements EnhancedTypeDeclaration { return this.implementation.isRequired; } - constructor(schemaWithFeatures: NewEnumImplementation, state: State, objectInitializer?: DeepPartial) { + constructor(schemaWithFeatures: EnumImplementation, state: State, objectInitializer?: DeepPartial) { if (!schemaWithFeatures.schema.language.csharp?.enum) { throw new Error(`ENUM AINT XMSENUM: ${schemaWithFeatures.schema.language.csharp?.name}`); } diff --git a/powershell/llcsharp/exports.ts b/powershell/llcsharp/exports.ts index 1a2054d48d..f9d66798e8 100644 --- a/powershell/llcsharp/exports.ts +++ b/powershell/llcsharp/exports.ts @@ -13,4 +13,4 @@ export * from './schema/schema-resolver'; export * from './schema/extended-type-declaration'; export * from './model/model-class-serializer'; export * from './schema/enum'; -export { NewBoolean } from './schema/boolean'; +export { Boolean } from './schema/boolean'; diff --git a/powershell/llcsharp/model/namespace.ts b/powershell/llcsharp/model/namespace.ts index 3950e2ab9c..9264799362 100644 --- a/powershell/llcsharp/model/namespace.ts +++ b/powershell/llcsharp/model/namespace.ts @@ -9,7 +9,7 @@ import { ImportDirective, Namespace } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { State } from '../generator'; -import { NewEnumImplementation } from '../schema/enum'; +import { EnumImplementation } from '../schema/enum'; import { EnhancedTypeDeclaration } from '../schema/extended-type-declaration'; import { ObjectImplementation } from '../schema/object'; import { SchemaDefinitionResolver } from '../schema/schema-resolver'; @@ -109,7 +109,7 @@ export class ModelsNamespace extends Namespace { return td; } - if (td instanceof NewEnumImplementation) { + if (td instanceof EnumImplementation) { if (schema.language.csharp?.enum) { const ec = state.project.supportNamespace.findClassByName(schema.language.csharp.enum.name); if (length(ec) === 0) { diff --git a/powershell/llcsharp/schema/Uuid.ts b/powershell/llcsharp/schema/Uuid.ts index fd6c5fcce1..7503480556 100644 --- a/powershell/llcsharp/schema/Uuid.ts +++ b/powershell/llcsharp/schema/Uuid.ts @@ -7,10 +7,10 @@ import { nameof } from '@azure-tools/codegen'; import { Variable } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { StringSchema } from '@azure-tools/codemodel'; -import { NewString } from './string'; +import { String } from './string'; -export class NewUuid extends NewString { +export class Uuid extends String { constructor(schema: StringSchema, isRequired: boolean) { super(schema, isRequired); } diff --git a/powershell/llcsharp/schema/array.ts b/powershell/llcsharp/schema/array.ts index 0974b2c8c7..9d1c35835d 100644 --- a/powershell/llcsharp/schema/array.ts +++ b/powershell/llcsharp/schema/array.ts @@ -21,7 +21,7 @@ import { Schema as NewSchema } from '@azure-tools/codemodel'; import { popTempVar, pushTempVar } from '../schema/primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; -export class NewArrayOf implements EnhancedTypeDeclaration { +export class ArrayOf implements EnhancedTypeDeclaration { public isXmlAttribute = false; public isNullable = true; get defaultOfType() { diff --git a/powershell/llcsharp/schema/binary.ts b/powershell/llcsharp/schema/binary.ts index 664c42ef15..49091f193c 100644 --- a/powershell/llcsharp/schema/binary.ts +++ b/powershell/llcsharp/schema/binary.ts @@ -14,7 +14,7 @@ import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { BinarySchema } from '@azure-tools/codemodel'; -export class NewBinary implements EnhancedTypeDeclaration { +export class Binary implements EnhancedTypeDeclaration { public isXmlAttribute = false; constructor(public schema: BinarySchema, public isRequired: boolean) { } diff --git a/powershell/llcsharp/schema/boolean.ts b/powershell/llcsharp/schema/boolean.ts index a2f259f46c..342b75a0ea 100644 --- a/powershell/llcsharp/schema/boolean.ts +++ b/powershell/llcsharp/schema/boolean.ts @@ -9,7 +9,7 @@ import { Schema } from '../code-model'; import { Schema as NewSchema, BooleanSchema } from '@azure-tools/codemodel'; import { NewPrimitive } from './primitive'; -export class NewBoolean extends NewPrimitive { +export class Boolean extends NewPrimitive { isXmlAttribute = false; jsonType = ClientRuntime.JsonBoolean; diff --git a/powershell/llcsharp/schema/byte-array.ts b/powershell/llcsharp/schema/byte-array.ts index 1089b5ee10..3a27284dbc 100644 --- a/powershell/llcsharp/schema/byte-array.ts +++ b/powershell/llcsharp/schema/byte-array.ts @@ -15,7 +15,7 @@ import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { ClientRuntime } from '../clientruntime'; -export class NewByteArray implements EnhancedTypeDeclaration { +export class ByteArray implements EnhancedTypeDeclaration { public isXmlAttribute = false; get declaration(): string { diff --git a/powershell/llcsharp/schema/char.ts b/powershell/llcsharp/schema/char.ts index 6e866a0091..d894a7487c 100644 --- a/powershell/llcsharp/schema/char.ts +++ b/powershell/llcsharp/schema/char.ts @@ -11,7 +11,7 @@ import { NewPrimitive } from './primitive'; import { length } from '@azure-tools/linq'; -export class NewChar extends NewPrimitive { +export class Char extends NewPrimitive { public isXmlAttribute = false; private choices?: Array; jsonType = ClientRuntime.JsonString; diff --git a/powershell/llcsharp/schema/date-time.ts b/powershell/llcsharp/schema/date-time.ts index 6881f116b6..e271fb11ff 100644 --- a/powershell/llcsharp/schema/date-time.ts +++ b/powershell/llcsharp/schema/date-time.ts @@ -15,7 +15,7 @@ import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema, DateSchema } from import { NewPrimitive } from './primitive'; -export class NewDateTime extends NewPrimitive { +export class DateTime extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonString; // public DateFormat = new StringExpression('yyyy-MM-dd'); @@ -109,14 +109,14 @@ export class NewDateTime extends NewPrimitive { -export class NewDateTime1123 extends NewDateTime { +export class DateTime1123 extends DateTime { public DateTimeFormat = new StringExpression('R'); constructor(schema: DateTimeSchema, isRequired: boolean) { super(schema, isRequired); } } -export class NewUnixTime extends NewPrimitive { +export class UnixTime extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/date.ts b/powershell/llcsharp/schema/date.ts index ddd1695954..c4a48751ab 100644 --- a/powershell/llcsharp/schema/date.ts +++ b/powershell/llcsharp/schema/date.ts @@ -6,10 +6,10 @@ import { StringExpression } from '@azure-tools/codegen-csharp'; import { Schema } from '../code-model'; import { DateSchema } from '@azure-tools/codemodel'; -import { NewDateTime } from './date-time'; +import { DateTime } from './date-time'; -export class NewDate extends NewDateTime { +export class Date extends DateTime { public DateTimeFormat = new StringExpression('yyyy-MM-dd'); constructor(schema: DateSchema, isRequired: boolean) { super(schema, isRequired); diff --git a/powershell/llcsharp/schema/duration.ts b/powershell/llcsharp/schema/duration.ts index bfa0f4e707..711398f9a5 100644 --- a/powershell/llcsharp/schema/duration.ts +++ b/powershell/llcsharp/schema/duration.ts @@ -13,7 +13,7 @@ import { NewPrimitive } from './primitive'; import { ClientRuntime } from '../clientruntime'; -export class NewDuration extends NewPrimitive { +export class Duration extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonString; diff --git a/powershell/llcsharp/schema/enum.ts b/powershell/llcsharp/schema/enum.ts index 1ae5ceb938..798329dbbe 100644 --- a/powershell/llcsharp/schema/enum.ts +++ b/powershell/llcsharp/schema/enum.ts @@ -5,10 +5,10 @@ import { Schema } from '../code-model'; import { Schema as NewSchema } from '@azure-tools/codemodel'; -import { NewString } from './string'; +import { String } from './string'; import { dotnet, toExpression } from '@azure-tools/codegen-csharp'; -export class NewEnumImplementation extends NewString { +export class EnumImplementation extends String { public isXmlAttribute = false; get isNullable(): boolean { return !this.isRequired; diff --git a/powershell/llcsharp/schema/integer.ts b/powershell/llcsharp/schema/integer.ts index 617283a1f4..0d39024b09 100644 --- a/powershell/llcsharp/schema/integer.ts +++ b/powershell/llcsharp/schema/integer.ts @@ -11,7 +11,7 @@ import { NumberSchema } from '@azure-tools/codemodel'; import { NewPrimitive } from './primitive'; -export class NewNumeric extends NewPrimitive { +export class Numeric extends NewPrimitive { public isXmlAttribute = false; public jsonType = ClientRuntime.JsonNumber; diff --git a/powershell/llcsharp/schema/schema-resolver.ts b/powershell/llcsharp/schema/schema-resolver.ts index 9f3353f04f..1e5c2a4c3f 100644 --- a/powershell/llcsharp/schema/schema-resolver.ts +++ b/powershell/llcsharp/schema/schema-resolver.ts @@ -8,19 +8,19 @@ import { codeModelSchema, ArraySchema, UnixTimeSchema, CodeModel, Schema as NewS import { codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3'; import { Schema } from '../code-model'; import * as message from '../messages'; -import { NewArrayOf } from './array'; -import { NewBinary } from './binary'; -import { NewBoolean } from './boolean'; -import { NewByteArray } from './byte-array'; -import { NewChar } from './char'; -import { NewDate } from './date'; -import { NewDateTime, NewDateTime1123, NewUnixTime } from './date-time'; -import { NewDuration } from './duration'; -import { NewEnumImplementation } from './enum'; -import { NewNumeric } from './integer'; +import { ArrayOf } from './array'; +import { Binary } from './binary'; +import { Boolean } from './boolean'; +import { ByteArray } from './byte-array'; +import { Char } from './char'; +import { Date } from './date'; +import { DateTime, DateTime1123, UnixTime } from './date-time'; +import { Duration } from './duration'; +import { EnumImplementation } from './enum'; +import { Numeric } from './integer'; import { ObjectImplementation } from './object'; -import { NewString } from './string'; -import { NewUuid } from './Uuid'; +import { String } from './string'; +import { Uuid } from './Uuid'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { PwshModel } from '../../utils/PwshModel'; import { ModelState } from '../../utils/model-state'; @@ -45,8 +45,8 @@ export class SchemaDefinitionResolver { // can be recursive! // handle boolean arrays as booleans (powershell will try to turn it into switches!) const ar = schema; - const elementType = (ar.elementType.type === SchemaType.Boolean) ? new NewBoolean(schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items')); - return new NewArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); + const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items')); + return new ArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems); } case SchemaType.Any: @@ -61,55 +61,55 @@ export class SchemaDefinitionResolver { case SchemaType.Time: case SchemaType.Credential: case SchemaType.String: { - return new NewString(schema, required); + return new String(schema, required); } case SchemaType.Binary: - return new NewBinary(schema, required); + return new Binary(schema, required); case SchemaType.Duration: - return new NewDuration(schema, required); + return new Duration(schema, required); case SchemaType.Uuid: - return new NewUuid(schema, required); + return new Uuid(schema, required); case SchemaType.DateTime: if ((schema).format === StringFormat.DateTimeRfc1123) { - return new NewDateTime1123(schema, required); + return new DateTime1123(schema, required); } - return new NewDateTime(schema, required); + return new DateTime(schema, required); case SchemaType.Date: - return new NewDate(schema, required); + return new Date(schema, required); case SchemaType.ByteArray: - return new NewByteArray(schema, required); + return new ByteArray(schema, required); case SchemaType.Boolean: - return new NewBoolean(schema, required); + return new Boolean(schema, required); case SchemaType.Integer: switch ((schema).precision) { case 64: - return new NewNumeric(schema, required, required ? 'long' : 'long?'); + return new Numeric(schema, required, required ? 'long' : 'long?'); // skip-for-time-being // case IntegerFormat.UnixTime: // return new UnixTime(schema, required); case 16: case 32: - return new NewNumeric(schema, required, required ? 'int' : 'int?'); + return new Numeric(schema, required, required ? 'int' : 'int?'); } // fallback to int if the format isn't recognized - return new NewNumeric(schema, required, required ? 'int' : 'int?'); + return new Numeric(schema, required, required ? 'int' : 'int?'); case SchemaType.UnixTime: - return new NewUnixTime(schema, required); + return new UnixTime(schema, required); case SchemaType.Number: switch ((schema).precision) { case 64: - return new NewNumeric(schema, required, required ? 'double' : 'double?'); + return new Numeric(schema, required, required ? 'double' : 'double?'); case 32: - return new NewNumeric(schema, required, required ? 'float' : 'float?'); + return new Numeric(schema, required, required ? 'float' : 'float?'); case 128: - return new NewNumeric(schema, required, required ? 'decimal' : 'decimal?'); + return new Numeric(schema, required, required ? 'decimal' : 'decimal?'); } // fallback to float if the format isn't recognized - return new NewNumeric(schema, required, required ? 'float' : 'float?'); + return new Numeric(schema, required, required ? 'float' : 'float?'); case SchemaType.Constant: return this.resolveTypeDeclaration((schema).valueType, required, state); @@ -119,12 +119,12 @@ export class SchemaDefinitionResolver { } case SchemaType.SealedChoice: if (schema.language.default.skip === true) { - return new NewString(schema, required); + return new String(schema, required); } - return new NewEnumImplementation(schema, required); + return new EnumImplementation(schema, required); case undefined: if (schema.extensions && schema.extensions['x-ms-enum']) { - return new NewEnumImplementation(schema, required); + return new EnumImplementation(schema, required); } // "any" case diff --git a/powershell/llcsharp/schema/string.ts b/powershell/llcsharp/schema/string.ts index ce4adcc71b..19ae332010 100644 --- a/powershell/llcsharp/schema/string.ts +++ b/powershell/llcsharp/schema/string.ts @@ -20,7 +20,7 @@ import { length } from '@azure-tools/linq'; /** A ETD for the c# string type. */ -export class NewString implements EnhancedTypeDeclaration { +export class String implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { diff --git a/powershell/plugins/plugin-tweak-model.ts b/powershell/plugins/plugin-tweak-model.ts index 4083a311e3..837d3f32c8 100644 --- a/powershell/plugins/plugin-tweak-model.ts +++ b/powershell/plugins/plugin-tweak-model.ts @@ -10,7 +10,7 @@ import { ModelState } from '../utils/model-state'; import { Channel, Host, Session, startSession } from '@azure-tools/autorest-extension-base'; import { defaultCipherList } from 'constants'; -import { NewString } from '../llcsharp/schema/string'; +import { String } from '../llcsharp/schema/string'; import { JsonType } from '../utils/schema'; export const HeaderProperty = 'HeaderProperty';