Restructuring Typespec migrate and add TypeSpec renaming, version update. (#1694)

* Adding back Cadl to all compiler public artifacts got renamed with TypeSpec

* initial restructuring

* Green compile with re-structuring mostly done.

* 0.41.0 file rename and package version update added

* TypeSpec replacement done

* tidy up the code with comments and output

* finishing up yargs

* update package.json to avoid rebase conflict

* adding test scenario

* adding cli help

* Fixing PR comments

* fixing PR checks

* tspconfig migration code working

* Update change log for migrate

* Remove eslint warning by setting no-console to false as this is a CLI tool
This commit is contained in:
Allen Zhang 2023-03-10 13:56:46 -08:00 коммит произвёл GitHub
Родитель 39305ceafc
Коммит cc73b3d099
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 1077 добавлений и 235 удалений

10
.vscode/launch.json поставляемый
Просмотреть файл

@ -135,6 +135,16 @@
"presentation": { "presentation": {
"hidden": true "hidden": true
} }
},
{
"type": "node",
"request": "launch",
"name": "Debug TypeSpec Migrate",
"program": "${workspaceFolder}/packages/migrate/dist/src/cli.js",
"smartStep": true,
"sourceMaps": true,
"skipFiles": ["<node_internals>/**/*.js"],
"cwd": "C:/Github/Sandbox/playground/cadl/migrate/0.37"
} }
], ],
"compounds": [ "compounds": [

Просмотреть файл

@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/migrate",
"comment": "Updating @typespec/migrate with better layering and 0.41 TypeSpec rename migration.",
"type": "none"
}
],
"packageName": "@typespec/migrate"
}

106
common/config/rush/pnpm-lock.yaml сгенерированный
Просмотреть файл

@ -56,6 +56,7 @@ specifiers:
'@types/prompts': ~2.4.1 '@types/prompts': ~2.4.1
'@types/react': ~18.0.5 '@types/react': ~18.0.5
'@types/react-dom': ~18.0.1 '@types/react-dom': ~18.0.1
'@types/semver': ^7.3.13
'@types/sinon': ~10.0.13 '@types/sinon': ~10.0.13
'@types/swagger-ui': ~3.52.0 '@types/swagger-ui': ~3.52.0
'@types/swagger-ui-react': ^4.11.0 '@types/swagger-ui-react': ^4.11.0
@ -65,6 +66,8 @@ specifiers:
'@typescript-eslint/parser': ^5.30.7 '@typescript-eslint/parser': ^5.30.7
'@typescript-eslint/utils': ~5.26.0 '@typescript-eslint/utils': ~5.26.0
'@typespec/compiler-v0.37': npm:@cadl-lang/compiler@0.37.0 '@typespec/compiler-v0.37': npm:@cadl-lang/compiler@0.37.0
'@typespec/compiler-v0.38': npm:@cadl-lang/compiler@0.38.0
'@typespec/compiler-v0.40': npm:@cadl-lang/compiler@0.40.0
'@vitejs/plugin-react': ~2.2.0 '@vitejs/plugin-react': ~2.2.0
'@vscode/vsce': ~2.15.0 '@vscode/vsce': ~2.15.0
ajv: ~8.11.2 ajv: ~8.11.2
@ -112,6 +115,7 @@ specifiers:
rimraf: ~3.0.2 rimraf: ~3.0.2
rollup: ~3.4.0 rollup: ~3.4.0
rollup-plugin-visualizer: ~5.8.0 rollup-plugin-visualizer: ~5.8.0
semver: ^7.3.8
sinon: ~15.0.1 sinon: ~15.0.1
source-map-support: ~0.5.19 source-map-support: ~0.5.19
strip-json-comments: ~4.0.0 strip-json-comments: ~4.0.0
@ -184,6 +188,7 @@ dependencies:
'@types/prompts': 2.4.2 '@types/prompts': 2.4.2
'@types/react': 18.0.27 '@types/react': 18.0.27
'@types/react-dom': 18.0.10 '@types/react-dom': 18.0.10
'@types/semver': 7.3.13
'@types/sinon': 10.0.13 '@types/sinon': 10.0.13
'@types/swagger-ui': 3.52.0 '@types/swagger-ui': 3.52.0
'@types/swagger-ui-react': 4.11.0 '@types/swagger-ui-react': 4.11.0
@ -193,6 +198,8 @@ dependencies:
'@typescript-eslint/parser': 5.49.0_eslint@8.33.0+typescript@4.9.5 '@typescript-eslint/parser': 5.49.0_eslint@8.33.0+typescript@4.9.5
'@typescript-eslint/utils': 5.26.0_eslint@8.33.0+typescript@4.9.5 '@typescript-eslint/utils': 5.26.0_eslint@8.33.0+typescript@4.9.5
'@typespec/compiler-v0.37': /@cadl-lang/compiler/0.37.0 '@typespec/compiler-v0.37': /@cadl-lang/compiler/0.37.0
'@typespec/compiler-v0.38': /@cadl-lang/compiler/0.38.0
'@typespec/compiler-v0.40': /@cadl-lang/compiler/0.40.0
'@vitejs/plugin-react': 2.2.0_vite@3.2.5 '@vitejs/plugin-react': 2.2.0_vite@3.2.5
'@vscode/vsce': 2.15.0 '@vscode/vsce': 2.15.0
ajv: 8.11.2 ajv: 8.11.2
@ -240,6 +247,7 @@ dependencies:
rimraf: 3.0.2 rimraf: 3.0.2
rollup: 3.4.0 rollup: 3.4.0
rollup-plugin-visualizer: 5.8.3_rollup@3.4.0 rollup-plugin-visualizer: 5.8.3_rollup@3.4.0
semver: 7.3.8
sinon: 15.0.1 sinon: 15.0.1
source-map-support: 0.5.21 source-map-support: 0.5.21
strip-json-comments: 4.0.0 strip-json-comments: 4.0.0
@ -1796,6 +1804,50 @@ packages:
yargs: 17.3.1 yargs: 17.3.1
dev: false dev: false
/@cadl-lang/compiler/0.38.0:
resolution: {integrity: sha512-SvKEbPdlNzkK7DWd/yM2+IiIVn593rv2bntzU+JY15LzbKmTDH6rrkArkr0nR7lMzcBXpBEEvU3vfRdeRrOTyg==}
engines: {node: '>=16.0.0'}
hasBin: true
dependencies:
'@babel/code-frame': 7.18.6
ajv: 8.11.2
change-case: 4.1.2
globby: 13.1.3
js-yaml: 4.1.0
mkdirp: 1.0.4
mustache: 4.2.0
node-fetch: 3.2.8
node-watch: 0.7.3
picocolors: 1.0.0
prettier: 2.7.1
prompts: 2.4.2
vscode-languageserver: 8.0.2
vscode-languageserver-textdocument: 1.0.8
yargs: 17.6.2
dev: false
/@cadl-lang/compiler/0.40.0:
resolution: {integrity: sha512-4u/Dnm39Ma+8wH0SDu7ya1+2oBRDiNByiRoijwyScHRec26UWLyWvHMvvU89ISU6O8Vwtq0bpmbD7FeJTnlbHw==}
engines: {node: '>=16.0.0'}
hasBin: true
dependencies:
'@babel/code-frame': 7.18.6
ajv: 8.11.2
change-case: 4.1.2
globby: 13.1.3
js-yaml: 4.1.0
mkdirp: 1.0.4
mustache: 4.2.0
node-fetch: 3.2.8
node-watch: 0.7.3
picocolors: 1.0.0
prettier: 2.8.3
prompts: 2.4.2
vscode-languageserver: 8.0.2
vscode-languageserver-textdocument: 1.0.8
yargs: 17.6.2
dev: false
/@colors/colors/1.5.0: /@colors/colors/1.5.0:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'} engines: {node: '>=0.1.90'}
@ -15283,7 +15335,7 @@ packages:
dev: false dev: false
file:projects/bundler.tgz: file:projects/bundler.tgz:
resolution: {integrity: sha512-2QTp6cW0nHCRYpyhBuY0LJxfQaXujdjaApLqkJHOJZFu5X++cSMFIDH7E8yTgCBBOTCes/my2erb7GMPuoUQHg==, tarball: file:projects/bundler.tgz} resolution: {integrity: sha512-3uJCkLkMa2sL0PL0VvTn3leCWM2k0YLtC1PaojgDs7UM3SFbg976ZFmFRZqKOM8NXPBM8IeIIRRqDk+/1uaZkg==, tarball: file:projects/bundler.tgz}
name: '@rush-temp/bundler' name: '@rush-temp/bundler'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15313,7 +15365,7 @@ packages:
dev: false dev: false
file:projects/compiler.tgz: file:projects/compiler.tgz:
resolution: {integrity: sha512-E/67YdnjZc8zQyM9W57MRhwNhI+iZ9Tl2LnmsrY5Dz+AKJ+BqWgEOsOAoLrxOuiXrYhVbtFzjwJf0Jzi8LdySA==, tarball: file:projects/compiler.tgz} resolution: {integrity: sha512-prwL+thcCHa8PuzSmzmSEhczD5W04oZdBBrluKtIYtH6NYUhLKcWZjMsTivpmP2c/7eenK9y1Suhr2l9yuBYVA==, tarball: file:projects/compiler.tgz}
name: '@rush-temp/compiler' name: '@rush-temp/compiler'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15382,7 +15434,7 @@ packages:
dev: false dev: false
file:projects/eslint-plugin.tgz: file:projects/eslint-plugin.tgz:
resolution: {integrity: sha512-IutMRWMzDh8ekd+G0zQIEVUaYm9eq57oxWdIc9gUWrUODcjS+GTnTkTSqPkuHjVp23r4rPuisOagH4cUzARaPw==, tarball: file:projects/eslint-plugin.tgz} resolution: {integrity: sha512-w4ufHmt3pf2RAe/JR+HroERTWVNA9sbGOmHWCRuo5CSiNyq93shzp6lOD3SDPynnvZ3yeT4ndWX5AwhGtcJndw==, tarball: file:projects/eslint-plugin.tgz}
name: '@rush-temp/eslint-plugin' name: '@rush-temp/eslint-plugin'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15402,7 +15454,7 @@ packages:
dev: false dev: false
file:projects/html-program-viewer.tgz: file:projects/html-program-viewer.tgz:
resolution: {integrity: sha512-ErwYPLrbB7F4e+bqtexPP2lFJluP/ifs0uIrxHV/Z85oQjwum8bdcQRKNEY2YSGFpYy+op1ZLVukL1lEGJRN2g==, tarball: file:projects/html-program-viewer.tgz} resolution: {integrity: sha512-4GhQ6FfR0kirc+AYmo5isMgknSaYLdWgObBc2IXz7wWuPeK5UkT0NGakggQ8i+8TNSgS+agLLRh6J+FxBuSRAA==, tarball: file:projects/html-program-viewer.tgz}
name: '@rush-temp/html-program-viewer' name: '@rush-temp/html-program-viewer'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15429,7 +15481,7 @@ packages:
dev: false dev: false
file:projects/http.tgz: file:projects/http.tgz:
resolution: {integrity: sha512-+8QdG+qvoJ0GOqYSy/IrdPG79DMrtyDx0IE1486I1TaUfvnj7e7LhXdAkVfEA6NxFZeEkwKGZ7Rxt8JZgTRuUg==, tarball: file:projects/http.tgz} resolution: {integrity: sha512-PQK1qg+HlfW/sJGbJJtsZ4cn0xU1E2Ce10LydTYlelq/MQRY7kR3OyFgPGV5zBJ13+Ol0SqsxtIYfLsPeuFZ2w==, tarball: file:projects/http.tgz}
name: '@rush-temp/http' name: '@rush-temp/http'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15447,7 +15499,7 @@ packages:
dev: false dev: false
file:projects/internal-build-utils.tgz: file:projects/internal-build-utils.tgz:
resolution: {integrity: sha512-JN9avh7DaGqtRw3kxRvvpDFdDrKokHIYNe52qpSZU8CBE1n6TQTQgumtjaTC6kxdaG4OpxnMaWAbbnZeu3QyQw==, tarball: file:projects/internal-build-utils.tgz} resolution: {integrity: sha512-uR5KWtoOTVIW4qfy2MrV08bLfV0tTiQXa9pCI6DW3EogZb6h+rsP3GRxBxR/G6n90fxITxoXHAt+1qXCSVFF1Q==, tarball: file:projects/internal-build-utils.tgz}
name: '@rush-temp/internal-build-utils' name: '@rush-temp/internal-build-utils'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15471,7 +15523,7 @@ packages:
dev: false dev: false
file:projects/library-linter.tgz: file:projects/library-linter.tgz:
resolution: {integrity: sha512-YxB1A4KBqtBOahnkriSZuPENCoaqNEI5e5WkLVa5Rzdd1inZoKi3EXXyX+nu1WmbgI3MgS7hoaMVfaIpYWtLxQ==, tarball: file:projects/library-linter.tgz} resolution: {integrity: sha512-RBc+g7VbuJd8BJH2tDXnA3Asq/6Tw8nF7PpVooB//7bk1iQTlL5SWCZLB0Z1uoRFQWV0mQAqBNG5D0aNpHI9VA==, tarball: file:projects/library-linter.tgz}
name: '@rush-temp/library-linter' name: '@rush-temp/library-linter'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15489,7 +15541,7 @@ packages:
dev: false dev: false
file:projects/lint.tgz: file:projects/lint.tgz:
resolution: {integrity: sha512-FGk655BBWZ30EdulGe5jklyl8JH0DT0vKqckZj8cLqUUtqYVuHIKpgUimH27vuk5wekRR3d1clMkK9Gqjr96uw==, tarball: file:projects/lint.tgz} resolution: {integrity: sha512-S8xoi5EgbtraHI6dFZif3L6ajGwuV9ZUPT79eaRgwHoC6Ib3y97LneXA60w1KUB0Uw3Si9lX3xhzSbTbZcFabg==, tarball: file:projects/lint.tgz}
name: '@rush-temp/lint' name: '@rush-temp/lint'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15507,27 +15559,37 @@ packages:
dev: false dev: false
file:projects/migrate.tgz: file:projects/migrate.tgz:
resolution: {integrity: sha512-6q4jXfgG3kBpX8Hg/tj9rsgSEO8Qfl8mJpe7XKrRx9/21MAdhSkocOnBA/IS6CBF5kQMVyumJxAnmH78yeLCsA==, tarball: file:projects/migrate.tgz} resolution: {integrity: sha512-0boLgSrZkcTsGaDluiAiGIPN+A5qXHoaQf10eYIuSua7/qrX5frkO77G2z9VIW6xzZuFbvUbsPP1kNN4503rEA==, tarball: file:projects/migrate.tgz}
name: '@rush-temp/migrate' name: '@rush-temp/migrate'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
'@types/js-yaml': 4.0.5
'@types/mocha': 10.0.1 '@types/mocha': 10.0.1
'@types/node': 18.11.18 '@types/node': 18.11.18
'@types/prettier': 2.6.0
'@types/semver': 7.3.13
'@types/yargs': 17.0.21
'@typespec/compiler-v0.37': /@cadl-lang/compiler/0.37.0 '@typespec/compiler-v0.37': /@cadl-lang/compiler/0.37.0
'@typespec/compiler-v0.38': /@cadl-lang/compiler/0.38.0
'@typespec/compiler-v0.40': /@cadl-lang/compiler/0.40.0
c8: 7.12.0 c8: 7.12.0
eslint: 8.33.0 eslint: 8.33.0
globby: 13.1.3 globby: 13.1.3
js-yaml: 4.1.0
mocha: 10.1.0 mocha: 10.1.0
mocha-junit-reporter: 2.2.0_mocha@10.1.0 mocha-junit-reporter: 2.2.0_mocha@10.1.0
mocha-multi-reporters: 1.5.1_mocha@10.1.0 mocha-multi-reporters: 1.5.1_mocha@10.1.0
prettier: 2.8.3
rimraf: 3.0.2 rimraf: 3.0.2
semver: 7.3.8
typescript: 4.9.5 typescript: 4.9.5
yargs: 17.6.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false dev: false
file:projects/openapi.tgz: file:projects/openapi.tgz:
resolution: {integrity: sha512-tqUvUFEZb3kr+MR/bSdTrTEj3HGtgY1jMHiUE8JCQcr09FzxOOHRVvplEu1reHm5y+JISLuXqzvU+1NRfOEIvQ==, tarball: file:projects/openapi.tgz} resolution: {integrity: sha512-f89N0ova9mFbnHCagBsbJCfxzBwDHRKNHzSy3BkRaynCDqG4sWBk1wsUI/FccTpyVt0oMi4fG3sa1O1if/ZM2A==, tarball: file:projects/openapi.tgz}
name: '@rush-temp/openapi' name: '@rush-temp/openapi'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15545,7 +15607,7 @@ packages:
dev: false dev: false
file:projects/openapi3.tgz: file:projects/openapi3.tgz:
resolution: {integrity: sha512-+PHWnKVDGJixPRMlC+6itwq88+fx5YAS4LXV0kZt8Ioa6zXxR51u2A8X8r/Mu/b6+CG6M551odTjvxeVKJ8MoQ==, tarball: file:projects/openapi3.tgz} resolution: {integrity: sha512-WweF+bBNr3tTrJxa4YKswxzppt7j3sNkr2xexhd/rhb0tvuZqTOA7goMbJfXF6V32f0Vt9F8DOj31hi+S/9KOw==, tarball: file:projects/openapi3.tgz}
name: '@rush-temp/openapi3' name: '@rush-temp/openapi3'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15565,7 +15627,7 @@ packages:
dev: false dev: false
file:projects/playground.tgz_rollup@3.4.0: file:projects/playground.tgz_rollup@3.4.0:
resolution: {integrity: sha512-c/ILHfQHEWFiRnAzJoFaJmNVbfHxQ2wc/T1a64rMX3VxMHlU+8mxlqAIacoqhRABlUfJWw4itIvU70x3tA/NWQ==, tarball: file:projects/playground.tgz} resolution: {integrity: sha512-j5/jnB6lpzAxxq1SIQ7HrVQZ5Pc4WrI4Rm0rZg8BeYniDTvrWRbbKeCHS35ni/hg0H/9ifPl74yLYB6lWhQYfQ==, tarball: file:projects/playground.tgz}
id: file:projects/playground.tgz id: file:projects/playground.tgz
name: '@rush-temp/playground' name: '@rush-temp/playground'
version: 0.0.0 version: 0.0.0
@ -15621,7 +15683,7 @@ packages:
dev: false dev: false
file:projects/prettier-plugin-typespec.tgz: file:projects/prettier-plugin-typespec.tgz:
resolution: {integrity: sha512-8LdJ1gW/+DKqFWba1QEPiADV9i2YYno4NxWQUwt4lAhOiZG9g0m8urceuGcA4uMZ1zujSq3W9XUhjcKi3jHdhA==, tarball: file:projects/prettier-plugin-typespec.tgz} resolution: {integrity: sha512-Zmdd/2jlSxrmiotCMceO58hihxNOVz+HpFNTyjQQjDTaTfT183DEMPMJhqDVUwELKrSh1vHIEf77aB8A+F7f5A==, tarball: file:projects/prettier-plugin-typespec.tgz}
name: '@rush-temp/prettier-plugin-typespec' name: '@rush-temp/prettier-plugin-typespec'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15639,7 +15701,7 @@ packages:
dev: false dev: false
file:projects/ref-doc.tgz: file:projects/ref-doc.tgz:
resolution: {integrity: sha512-F05bWju+vc/BFJ4CslZBKji0W2zzeUYXYy9m301kHclKjj3a5yxZzgxlvaGLUo1HIrsVterjimr7qfoG1qNcyw==, tarball: file:projects/ref-doc.tgz} resolution: {integrity: sha512-G5rvHzQFxLZFKHFTNgLf+yEnV972SGx2vq6vTJRrlrG8mOGjMXwwrGAxoYB1YWvwwu+g/ZNeP9BapiTSAO8NxQ==, tarball: file:projects/ref-doc.tgz}
name: '@rush-temp/ref-doc' name: '@rush-temp/ref-doc'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15661,7 +15723,7 @@ packages:
dev: false dev: false
file:projects/rest.tgz: file:projects/rest.tgz:
resolution: {integrity: sha512-ptBSo46OFKkgaUZZb0kjmBBuZg/egYcGFIRaYqiS7oaoigs06co1hjT+ji4FE+7NfZAD1jNA38Kd6chFH8SVkw==, tarball: file:projects/rest.tgz} resolution: {integrity: sha512-jyovPCwq3SPwu04TBokC9pAGvJ7bmxHv2FmorbQk5M+LTE0asW7gGr/uzBnGUn1NvdMov5nJeQ3A2GQpWAb0bA==, tarball: file:projects/rest.tgz}
name: '@rush-temp/rest' name: '@rush-temp/rest'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15679,7 +15741,7 @@ packages:
dev: false dev: false
file:projects/samples.tgz: file:projects/samples.tgz:
resolution: {integrity: sha512-lnDPU+AYTd0YwkPNpnzismxBohIgIhxeZPFzLYsFQPm73JIt6nqdECwuu4B8G3kG/KhA0ds9qqy+suF6WI1uTw==, tarball: file:projects/samples.tgz} resolution: {integrity: sha512-2DI/CQYaa89lmy4nL5qWUUwcM8985A8tSobbxoUrxj7AssjgwIGZIHAYaLd50ksTWufDsHEUJa8VyaEIER7+rw==, tarball: file:projects/samples.tgz}
name: '@rush-temp/samples' name: '@rush-temp/samples'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15691,7 +15753,7 @@ packages:
dev: false dev: false
file:projects/spec.tgz: file:projects/spec.tgz:
resolution: {integrity: sha512-pj6X+JJQIRzYDmPmyx9tcoRvPndJn1RrI/AJApESrfXWUNF7kOnAunmGd7VvESJfpOhFvLl50fAdg9r5cuhNVw==, tarball: file:projects/spec.tgz} resolution: {integrity: sha512-vrai9fKUuwUNksrn4RBWCpxjoxcXclJsa+bpdGVphztqaR9agH5SF9GeQjiSUqJbaedmoI9Mhf2/TxHKYTRRKA==, tarball: file:projects/spec.tgz}
name: '@rush-temp/spec' name: '@rush-temp/spec'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15706,7 +15768,7 @@ packages:
dev: false dev: false
file:projects/tmlanguage-generator.tgz: file:projects/tmlanguage-generator.tgz:
resolution: {integrity: sha512-vr/oeq6/6mo79rEz2Et39cROBjxYr7rwX7NvJkt/cLPvq3CzK22kgixQkyPhScyCZVPW4WRmv2iurKbH8s7G+Q==, tarball: file:projects/tmlanguage-generator.tgz} resolution: {integrity: sha512-ZVMOy0RcZZp6MTJEwqmNHdtRLncamntvo6qsBM39FSVCXZMQTGWliddOlhUMxNYgZ8bTopCUkjvbOH8daq1EAw==, tarball: file:projects/tmlanguage-generator.tgz}
name: '@rush-temp/tmlanguage-generator' name: '@rush-temp/tmlanguage-generator'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15722,13 +15784,13 @@ packages:
dev: false dev: false
file:projects/typespec-vs.tgz: file:projects/typespec-vs.tgz:
resolution: {integrity: sha512-S8FACAX4yQTj2TnM1wafi55Z9SFJnTvW4MaDOlIkO2x48DpnbHZaBzSNIn43i4iLLvYcpAnazuFNKk2dwtEiIg==, tarball: file:projects/typespec-vs.tgz} resolution: {integrity: sha512-athxR1f8AFsdNoI/vQtis+QxyR7zOj2naftG32eQFJNEF+1yoqnS1sJp8x1uFw5NbHSS5F11qbWCH9hukoAx7Q==, tarball: file:projects/typespec-vs.tgz}
name: '@rush-temp/typespec-vs' name: '@rush-temp/typespec-vs'
version: 0.0.0 version: 0.0.0
dev: false dev: false
file:projects/typespec-vscode.tgz: file:projects/typespec-vscode.tgz:
resolution: {integrity: sha512-cKCr5r+q3U04L4+WvAh3YLMHGQW0jP26/eD4YoQzW0qF5TfRg1qTTVAnCONSggiHGR9GGhGVl2kWefA6OHpt3w==, tarball: file:projects/typespec-vscode.tgz} resolution: {integrity: sha512-HAVnHFKRFTgbhP6xGQn72iEoAGXWGhVwAp31yAPLP04YBVDvmBQ6fCREbxS+ktIj8Qyt6XBdfuOoKMsDayl8QA==, tarball: file:projects/typespec-vscode.tgz}
name: '@rush-temp/typespec-vscode' name: '@rush-temp/typespec-vscode'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15754,7 +15816,7 @@ packages:
dev: false dev: false
file:projects/versioning.tgz: file:projects/versioning.tgz:
resolution: {integrity: sha512-kZZ3sFk/i3U9Sl0TxlLaxRHEMSmvAVy3EKpFIwhH+7wEQN+cpwZvuBpuCWj263JQK7yIE1js973eKXajZIGPcg==, tarball: file:projects/versioning.tgz} resolution: {integrity: sha512-BHQ5YRNk+yL5yYQlpnNNUaM73kstHRnuTxTviUlrU+m1Yvnf2tA/KGoMOytNrWfTBM1zNgSjNhW3Gr7hTt8X/Q==, tarball: file:projects/versioning.tgz}
name: '@rush-temp/versioning' name: '@rush-temp/versioning'
version: 0.0.0 version: 0.0.0
dependencies: dependencies:
@ -15772,7 +15834,7 @@ packages:
dev: false dev: false
file:projects/website.tgz_@types+react@18.0.27: file:projects/website.tgz_@types+react@18.0.27:
resolution: {integrity: sha512-DP2BOM3gpf89GPfCB2zPKEjHbsnbIovcSyTyh86cAk7hQviHDQvStyVLE4PmTZDM/FNF60uwaKGt4GM48BrYNQ==, tarball: file:projects/website.tgz} resolution: {integrity: sha512-msvMDz9MVQ3A1NnfEzpImCAHAKqRK81K+K1C2QhmYDSeyJuqMPqc6fECZNAiqmCLVaxHqqH6kmoLXoEOB7twpQ==, tarball: file:projects/website.tgz}
id: file:projects/website.tgz id: file:projects/website.tgz
name: '@rush-temp/website' name: '@rush-temp/website'
version: 0.0.0 version: 0.0.0

Просмотреть файл

@ -4,4 +4,7 @@ module.exports = {
plugins: ["@typespec/eslint-plugin"], plugins: ["@typespec/eslint-plugin"],
extends: ["@typespec/eslint-config-typespec", "plugin:@typespec/eslint-plugin/recommended"], extends: ["@typespec/eslint-config-typespec", "plugin:@typespec/eslint-plugin/recommended"],
parserOptions: { tsconfigRootDir: __dirname }, parserOptions: { tsconfigRootDir: __dirname },
rules: {
"no-console": "off",
},
}; };

Просмотреть файл

@ -38,21 +38,31 @@
"!dist/test/**" "!dist/test/**"
], ],
"dependencies": { "dependencies": {
"globby": "~13.1.1",
"@typespec/compiler": "~0.41.0", "@typespec/compiler": "~0.41.0",
"@typespec/compiler-v0.37": "npm:@cadl-lang/compiler@0.37.0" "@typespec/compiler-v0.37": "npm:@cadl-lang/compiler@0.37.0",
"@typespec/compiler-v0.38": "npm:@cadl-lang/compiler@0.38.0",
"@typespec/compiler-v0.40": "npm:@cadl-lang/compiler@0.40.0",
"globby": "~13.1.1",
"prettier": "~2.8.1",
"semver": "^7.3.8",
"yargs": "~17.6.2",
"js-yaml": "~4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/mocha": "~10.0.0", "@types/mocha": "~10.0.0",
"@types/node": "~18.11.9", "@types/node": "~18.11.9",
"@types/js-yaml": "~4.0.1",
"@types/prettier": "2.6.0",
"@types/semver": "^7.3.13",
"@types/yargs": "~17.0.2",
"@typespec/compiler": "~0.41.0", "@typespec/compiler": "~0.41.0",
"@typespec/eslint-config-typespec": "~0.6.0", "@typespec/eslint-config-typespec": "~0.6.0",
"@typespec/eslint-plugin": "~0.41.0", "@typespec/eslint-plugin": "~0.41.0",
"c8": "~7.12.0",
"eslint": "^8.12.0", "eslint": "^8.12.0",
"mocha": "~10.1.0", "mocha": "~10.1.0",
"mocha-junit-reporter": "~2.2.0", "mocha-junit-reporter": "~2.2.0",
"mocha-multi-reporters": "~1.5.1", "mocha-multi-reporters": "~1.5.1",
"c8": "~7.12.0",
"rimraf": "~3.0.2", "rimraf": "~3.0.2",
"typescript": "~4.9.3" "typescript": "~4.9.3"
} }

Просмотреть файл

@ -1,22 +1,129 @@
#!/usr/bin/env node #!/usr/bin/env node
/* eslint-disable no-console */ /* eslint-disable no-console */
import { migrateTypeSpecFiles } from "./migrate.js"; import { MANIFEST, NodePackage, resolvePath } from "@typespec/compiler";
import { migrateModelToScalar } from "./migrations/v0.38/model-to-scalars.js"; import * as fs from "fs";
import { readFile } from "fs/promises";
import * as semver from "semver";
import yargs from "yargs";
import { migrationConfigurations } from "./migration-config.js";
import {
migrateFileRename,
migratePackageVersion,
migrateTextFiles,
migrateTypeSpecFiles,
} from "./migration-impl.js";
import { MigrationKind } from "./migration-types.js";
import { findTypeSpecFiles } from "./utils.js"; import { findTypeSpecFiles } from "./utils.js";
async function main() { interface Options {
const files = await findTypeSpecFiles(process.cwd()); path: string;
const result = await migrateTypeSpecFiles(files, migrateModelToScalar); tspVersion: string;
}
if (result.fileChanged.length === 0) { async function main() {
console.log("No typespec files migrated, no change detected."); console.log(`TypeSpec migration tool v${MANIFEST.version}\n`);
} else {
console.log(`Updated ${result.fileChanged.length} typespec files:`); const cliOptions: Options = await yargs(process.argv.slice(2))
for (const file of result.fileChanged) { .option("path", {
console.log(` - ${file}`); alias: "p",
describe: "Path to the input directory. Defaults to the current directory.",
type: "string",
default: process.cwd(),
})
.option("tspVersion", {
alias: "t",
describe:
"Specifies the TypeSpec compiler version used by the input. Defaults to the version of the compiler package in package.json.",
type: "string",
default: "",
})
.help().argv;
const PackageJsonFile = "package.json";
if (cliOptions.tspVersion.length === 0) {
// Locate current package.json
const pkgFile = resolvePath(cliOptions.path, PackageJsonFile);
const packageJson: NodePackage = JSON.parse(await readFile(pkgFile, "utf-8"));
// Locate current compiler version
const CadlCompiler = "@cadl-lang/compiler";
const TypeSpecCompiler = "@typespec/compiler";
if (
packageJson?.devDependencies !== undefined &&
packageJson?.devDependencies[CadlCompiler] !== undefined
) {
cliOptions.tspVersion = packageJson.devDependencies[CadlCompiler];
} else if (
packageJson?.devDependencies !== undefined &&
packageJson?.devDependencies[TypeSpecCompiler] !== undefined
) {
cliOptions.tspVersion = packageJson.devDependencies[TypeSpecCompiler];
} else {
console.error("Unable to find TypeSpec compiler version in package.json.");
return;
} }
console.log("This is a best effort migration, double check everything was migrated correctly."); }
if (!fs.existsSync(cliOptions.path)) {
console.error(`Path not found. ${cliOptions.path}`);
return;
}
let changesMade = false;
// Iterate thru migration configuration and invoke migration functions
console.log(`Current Typespec version ${cliOptions.tspVersion}.`);
const stepKeys = Object.keys(migrationConfigurations);
for (const key of stepKeys) {
if (semver.gt(key, cliOptions.tspVersion)) {
console.log(
`Migration step found to upgrade from ${cliOptions.tspVersion} to ${key}. Migrating...`
);
for (const migrationStep of migrationConfigurations[key]) {
const files = await findTypeSpecFiles(cliOptions.path);
switch (migrationStep.kind) {
case MigrationKind.AstContentMigration:
const result = await migrateTypeSpecFiles(files, migrationStep);
// If migration has been performed log status
if (result.filesChanged.length > 0) {
changesMade = true;
console.log(`Updated ${result.filesChanged.length} TypeSpec files:`);
for (const file of result.filesChanged) {
console.log(` - ${file}`);
}
}
break;
case MigrationKind.FileContentMigration:
changesMade = await migrateTextFiles(files, migrationStep);
break;
case MigrationKind.FileRename:
changesMade = await migrateFileRename(files, migrationStep);
break;
case MigrationKind.PackageVersionUpdate:
const pkgFile = resolvePath(cliOptions.path, PackageJsonFile);
changesMade = await migratePackageVersion(pkgFile, migrationStep);
break;
default:
console.log(`Unexpected error: unknown migration kind: ${migrationStep} `);
}
}
cliOptions.tspVersion = key;
} else {
console.log(
`${cliOptions.tspVersion} is already greater than or equal to ${key}. Migration step skipped...`
);
}
}
if (changesMade) {
console.log(
"\nThis is a best effort migration, double check that everything was migrated correctly."
);
} else {
console.log("\nNo typespec files have been migrated.");
} }
} }

Просмотреть файл

@ -1,119 +0,0 @@
import { TextRange } from "@typespec/compiler";
import { readFile, writeFile } from "fs/promises";
import {
Migration,
TypeSpecCompiler,
TypeSpecCompilers,
TypeSpecCompilerVersion,
} from "./migrations/migration.js";
export interface MigrationResult {
fileChanged: string[];
}
export async function migrateTypeSpecFiles(files: string[], migration: Migration<any>) {
const fromCompiler = await loadCompiler(migration.from);
const toCompiler = await loadCompiler(migration.to);
return migrateTypeSpecFilesInternal(fromCompiler, toCompiler, files, migration);
}
export async function migrateTypeSpecContent(content: string, migration: Migration<any>) {
const fromCompiler = await loadCompiler(migration.from);
const toCompiler = await loadCompiler(migration.to);
return migrateTypeSpecContentInternal(fromCompiler, toCompiler, content, migration);
}
async function loadCompiler<V extends TypeSpecCompilerVersion>(
version: V
): Promise<TypeSpecCompilers[V]> {
try {
return await import(`@typespec/compiler-v${version}`);
} catch {
return (await import("@typespec/compiler")) as any;
}
}
async function migrateTypeSpecFilesInternal(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
files: string[],
migration: Migration<any>
): Promise<MigrationResult> {
const result: MigrationResult = {
fileChanged: [],
};
for (const file of files) {
if (await migrateTypeSpecFile(fromCompiler, toCompiler, file, migration)) {
result.fileChanged.push(file);
}
}
return result;
}
async function migrateTypeSpecFile(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
filename: string,
migration: Migration<any>
): Promise<boolean> {
const buffer = await readFile(filename);
const content = buffer.toString();
const [newContent, changed] = migrateTypeSpecContentInternal(
fromCompiler,
toCompiler,
content,
migration
);
await writeFile(filename, newContent);
return changed;
}
function migrateTypeSpecContentInternal(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
content: string,
migration: Migration<any>
): [string, boolean] {
const parsed = fromCompiler.parse(content);
const actions = migration
.migrate(createMigrationContext(parsed), fromCompiler, parsed as any)
.sort((a, b) => a.target.pos - b.target.pos);
if (actions.length === 0) {
return [content, false];
}
const segments = [];
let last = 0;
for (const action of actions) {
segments.push(content.slice(last, action.target.pos));
segments.push(action.content);
last = action.target.end;
}
segments.push(content.slice(last, -1));
const newContent = segments.join("");
try {
return [(toCompiler as any).formatTypeSpec(newContent), true];
} catch (e) {
// eslint-disable-next-line no-console
console.error("Failed to format new code", e);
return [newContent, true];
}
}
function createMigrationContext(root: any) {
function printNode(node: TextRange) {
return root.file.text.slice(node.pos, node.end);
}
function printNodes(nodes: readonly TextRange[]): string {
if (nodes.length === 0) {
return "";
}
const first = nodes[0];
const last = nodes[nodes.length - 1];
return root.file.text.slice(first.pos, last.end);
}
return { printNode, printNodes };
}

Просмотреть файл

@ -0,0 +1,35 @@
import { MigrationStepsDictionary } from "./migration-types.js";
import { migrateModelToScalar } from "./migrations/v0.38/model-to-scalars.js";
import {
migrateCadlNameToTypeSpec,
migrateTspConfigFile,
renameCadlFileNames,
updatePackageVersion,
} from "./migrations/v0.41/typespec-rename.js";
// Update here before release.
export type TypeSpecCompilerCurrent = typeof import("@typespec/compiler");
export type TypeSpecCompilerV0_37 = typeof import("@typespec/compiler-v0.37");
export type TypeSpecCompilerV0_38 = typeof import("@typespec/compiler-v0.38");
export type TypeSpecCompilerV0_40 = typeof import("@typespec/compiler-v0.40");
export type TypeSpecCompilerV0_41 = TypeSpecCompilerCurrent;
/** Defines the list of compiler versions will be used */
export type TypeSpecCompilers = {
"0.37.0": TypeSpecCompilerV0_37;
"0.38.0": TypeSpecCompilerV0_38;
"0.40.0": TypeSpecCompilerV0_40;
"0.41.0": TypeSpecCompilerV0_41;
};
/** Please define the list of migration steps for each version.
* Step sequence is respected */
export const migrationConfigurations: MigrationStepsDictionary = {
"0.38.0": [migrateModelToScalar],
"0.41.0": [
migrateCadlNameToTypeSpec,
renameCadlFileNames,
updatePackageVersion,
migrateTspConfigFile,
],
};

Просмотреть файл

@ -0,0 +1,227 @@
import { NodePackage, TextRange } from "@typespec/compiler";
import * as fs from "fs";
import { readFile, writeFile } from "fs/promises";
import prettier from "prettier";
import { TypeSpecCompilers } from "./migration-config.js";
import {
AstContentMigrateAction,
AstContentMigration,
FileContentMigration,
FileRenameMigration,
MigrationKind,
PackageVersionUpdateMigration,
TypeSpecCompiler,
TypeSpecCompilerVersion,
} from "./migration-types.js";
export interface MigrationResult {
filesChanged: string[];
}
/** Main function for migrating text file content */
export async function migrateTextFiles(files: string[], migration: FileContentMigration) {
const actions = await migration.migrate(files);
if (actions.length > 0) {
console.log(`Updating text content of ${actions.length} file(s):`);
for (const action of actions) {
console.log(` - ${action.fileName}`);
await writeFile(action.fileName, action.newContent);
}
}
return actions.length > 0 ? true : false;
}
/** Main function for migrating typespec file content */
export async function migrateTypeSpecFiles(files: string[], migration: AstContentMigration<any>) {
const fromCompiler = await loadCompiler(migration.from);
const toCompiler = await loadCompiler(migration.to);
return migrateTypeSpecFilesInternal(fromCompiler, toCompiler, files, migration);
}
/** Main function for rename files */
export async function migrateFileRename(
files: string[],
migration: FileRenameMigration
): Promise<boolean> {
const renameActions = migration.migrate(files);
let changesMade = false;
if (renameActions.length === 0) return changesMade;
console.log(`Renaming ${renameActions.length} file(s):`);
for (const action of renameActions) {
changesMade = true;
console.log(` - ${action.sourceFileName} -> ${action.targetFileName}`);
fs.rename(action.sourceFileName, action.targetFileName, (err) => {
if (err) {
console.error(
`Error renaming file from ${action.sourceFileName} to ${action.targetFileName}`,
err
);
}
});
}
return changesMade;
}
/** Main function for migrating package versions in the package.json */
export async function migratePackageVersion(
pkgFile: string,
migration: PackageVersionUpdateMigration
): Promise<boolean> {
const packageJson: NodePackage = JSON.parse(await readFile(pkgFile, "utf-8"));
const actions = migration.migrate(packageJson);
let changeMade = false;
if (actions.length === 0) return changeMade;
console.log(`Updating ${actions.length} package(s):`);
for (const action of actions) {
if (
packageJson.dependencies !== undefined &&
packageJson.dependencies[action.packageName] !== undefined
) {
if (action.renamePackageName !== undefined) {
delete packageJson.dependencies[action.packageName];
packageJson.dependencies[action.renamePackageName] = action.toVersion;
} else packageJson.dependencies[action.packageName] = action.toVersion;
console.log(` - dependencies: ${action.renamePackageName} -> ${action.toVersion}.`);
changeMade = true;
}
if (
packageJson.devDependencies !== undefined &&
packageJson.devDependencies[action.packageName] !== undefined
) {
if (action.renamePackageName !== undefined) {
delete packageJson.devDependencies[action.packageName];
packageJson.devDependencies[action.renamePackageName] = action.toVersion;
} else packageJson.devDependencies[action.packageName] = action.toVersion;
console.log(` - devDependencies: ${action.renamePackageName} -> ${action.toVersion}.`);
changeMade = true;
}
}
if (changeMade) {
const prettyJsonString = prettier.format(JSON.stringify(packageJson), { parser: "json" });
fs.writeFileSync(pkgFile, prettyJsonString);
}
return changeMade;
}
/** This is used by test code to migrate single file content */
export async function migrateTypeSpecContent(content: string, migration: AstContentMigration<any>) {
const fromCompiler = await loadCompiler(migration.from);
const toCompiler = await loadCompiler(migration.to);
return migrateTypeSpecContentInternal(fromCompiler, toCompiler, content, migration);
}
async function loadCompiler<V extends TypeSpecCompilerVersion>(
version: V
): Promise<TypeSpecCompilers[V]> {
try {
return await import(`@typespec/compiler-v${version}`);
} catch {
return (await import("@typespec/compiler")) as any;
}
}
async function migrateTypeSpecFilesInternal(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
files: string[],
migration: AstContentMigration<any>
): Promise<MigrationResult> {
const result: MigrationResult = {
filesChanged: [],
};
for (const file of files) {
if (await migrateTypeSpecFile(fromCompiler, toCompiler, file, migration)) {
result.filesChanged.push(file);
}
}
return result;
}
async function migrateTypeSpecFile(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
filename: string,
migration: AstContentMigration<any>
): Promise<boolean> {
const buffer = await readFile(filename);
const content = buffer.toString();
const [newContent, changed] = migrateTypeSpecContentInternal(
fromCompiler,
toCompiler,
content,
migration
);
await writeFile(filename, newContent);
return changed;
}
function migrateTypeSpecContentInternal(
fromCompiler: TypeSpecCompiler,
toCompiler: TypeSpecCompiler,
content: string,
migration: AstContentMigration<any>
): [string, boolean] {
const parsed = fromCompiler.parse(content);
const actions = migration
.migrate(createMigrationContext(parsed), fromCompiler, parsed as any)
.filter(
(action): action is AstContentMigrateAction =>
action.kind === MigrationKind.AstContentMigration
)
.sort((a, b) => a.target.pos - b.target.pos);
return ContentMigration(toCompiler, content, actions);
}
function ContentMigration(
toCompiler: TypeSpecCompiler,
content: string,
actions: AstContentMigrateAction[]
): [string, boolean] {
if (actions.length === 0) {
return [content, false];
}
const segments = [];
let last = 0;
for (const action of actions) {
segments.push(content.slice(last, action.target.pos));
segments.push(action.content);
last = action.target.end;
}
segments.push(content.slice(last, -1));
const newContent = segments.join("");
try {
return [(toCompiler as any).formatTypeSpec(newContent), true];
} catch (e) {
// eslint-disable-next-line no-console
console.error("Failed to format new code", e);
return [newContent, true];
}
}
function createMigrationContext(root: any) {
function printNode(node: TextRange) {
return root.file.text.slice(node.pos, node.end);
}
function printNodes(nodes: readonly TextRange[]): string {
if (nodes.length === 0) {
return "";
}
const first = nodes[0];
const last = nodes[nodes.length - 1];
return root.file.text.slice(first.pos, last.end);
}
return { printNode, printNodes };
}

Просмотреть файл

@ -0,0 +1,161 @@
import { NodePackage, TextRange } from "@typespec/compiler";
import { TypeSpecCompilers } from "./migration-config.js";
/** Defines the configuration dictionary */
export interface MigrationStepsDictionary {
[key: string]: Migration[];
}
/** This is the list of supported migration steps */
export enum MigrationKind {
AstContentMigration,
FileContentMigration,
FileRename,
PackageVersionUpdate,
}
/** Defines all migration actions */
export type MigrateAction =
| AstContentMigrateAction
| FileContentMigrationAction
| FileRenameAction
| PackageVersionUpdateAction;
/** Defines all migration functions that can be implemented by version specific migration functions.
* These functions should return corresponding array migration actions to be performed.*/
export type Migration =
| AstContentMigration<TypeSpecCompilerVersion>
| FileContentMigration
| FileRenameMigration
| PackageVersionUpdateMigration;
/** Type of imported versions of tsp compilers defined in migration-config.ts. */
export type TypeSpecCompiler = TypeSpecCompilers[keyof TypeSpecCompilers];
/** Key type of all compiler versions defined in migration-config.ts. */
export type TypeSpecCompilerVersion = keyof TypeSpecCompilers;
/** Migration Context type that contains some helper functions */
export interface MigrationContext {
/**
* Print the text range as it is.
*/
printNode(node: TextRange): string;
/**
* Print the entire text range from teh first node to the last.(Including anything in between the nodes.)
*/
printNodes(node: readonly TextRange[]): string;
}
export interface MigrationBase {
name: string;
kind: MigrationKind;
}
/** ContentMigration interface definition. */
export interface AstContentMigration<TFrom extends TypeSpecCompilerVersion> extends MigrationBase {
kind: MigrationKind.AstContentMigration;
/**
* Compiler version.
*/
from: TFrom;
/**
* Target version
*/
to: TypeSpecCompilerVersion;
/**
* Migrate logic.
* @param compilerInstance Instance of the compiler at the `from` version.
* @param script TypeSpec Script source node.
*/
migrate(
context: MigrationContext,
compilerInstance: TypeSpecCompilers[TFrom],
script: unknown
): MigrateAction[];
}
export interface FileContentMigration extends MigrationBase {
kind: MigrationKind.FileContentMigration;
migrate(fileNames: string[]): Promise<FileContentMigrationAction[]>;
}
/** File Rename migration interface definition. */
export interface FileRenameMigration extends MigrationBase {
kind: MigrationKind.FileRename;
migrate(fileNames: string[]): FileRenameAction[];
}
/** Package version update migration interface definition. */
export interface PackageVersionUpdateMigration extends MigrationBase {
kind: MigrationKind.PackageVersionUpdate;
migrate(pkg: NodePackage): PackageVersionUpdateAction[];
}
/** Base class for migration actions */
export interface MigrateActionBase {
kind: MigrationKind;
}
/** Migration action that modifies contents */
export interface AstContentMigrateAction extends MigrateActionBase {
kind: MigrationKind.AstContentMigration;
target: TextRange; // TypeSpec compiler node
/**
* Replaced content
*/
content: string;
}
/** Migration action that renames a file */
export interface FileRenameAction extends MigrateActionBase {
kind: MigrationKind.FileRename;
sourceFileName: string;
targetFileName: string;
}
export interface FileContentMigrationAction extends MigrateActionBase {
kind: MigrationKind.FileContentMigration;
fileName: string;
newContent: string;
}
/** Migration action that updates a package version */
export interface PackageVersionUpdateAction extends MigrateActionBase {
kind: MigrationKind.PackageVersionUpdate;
packageName: string;
renamePackageName?: string;
toVersion: string;
}
/** Helper functions to define a custom migration function */
export function createContentMigration<TFrom extends TypeSpecCompilerVersion>(
migration: AstContentMigration<TFrom>
): AstContentMigration<TFrom> {
return migration;
}
/** Helper functions to define a custom migration function */
export function createFileRenameMigration(migration: FileRenameMigration): FileRenameMigration {
return migration;
}
/** Helper functions to define a custom migration function */
export function createFileContentMigration(migration: FileContentMigration): FileContentMigration {
return migration;
}
/** Helper functions to define a custom migration function */
export function createPackageVersionMigration(
migration: PackageVersionUpdateMigration
): PackageVersionUpdateMigration {
return migration;
}

Просмотреть файл

@ -1,67 +0,0 @@
import { TextRange } from "@typespec/compiler";
export type MigrationKind = "Syntax";
// Update here before release.
export type TypeSpecCompilerCurrent = typeof import("@typespec/compiler");
export type TypeSpecCompilerV0_38 = TypeSpecCompilerCurrent;
export type TypeSpecCompilerV0_37 = typeof import("@typespec/compiler-v0.37");
export type TypeSpecCompilers = {
"0.37": TypeSpecCompilerV0_37;
"0.38": TypeSpecCompilerV0_38;
};
export type TypeSpecCompiler = TypeSpecCompilers[keyof TypeSpecCompilers];
export type TypeSpecCompilerVersion = keyof TypeSpecCompilers;
export interface MigrationContext {
/**
* Print the text range as it is.
*/
printNode(node: TextRange): string;
/**
* Print the entire text range from teh first node to the last.(Including anything in between the nodes.)
*/
printNodes(node: readonly TextRange[]): string;
}
export interface Migration<TFrom extends TypeSpecCompilerVersion> {
name: string;
kind: "Syntax";
/**
* Compiler version.
*/
from: TFrom;
/**
* Target version
*/
to: TypeSpecCompilerVersion;
/**
* Migrate logic.
* @param compilerInstance Instance of the compiler at the `from` version.
* @param script TypeSpec Script source node.
*/
migrate(
context: MigrationContext,
compilerInstance: TypeSpecCompilers[TFrom],
script: unknown
): MigrateAction[];
}
export interface MigrateAction {
target: TextRange; // TypeSpec compiler node
/**
* Replaced content
*/
content: string;
}
export function createMigration<TFrom extends TypeSpecCompilerVersion>(
migration: Migration<TFrom>
): Migration<TFrom> {
return migration;
}

Просмотреть файл

@ -3,18 +3,19 @@ import type {
Node, Node,
TemplateParameterDeclarationNode, TemplateParameterDeclarationNode,
} from "@typespec/compiler-v0.37"; } from "@typespec/compiler-v0.37";
import { TypeSpecCompilerV0_37 } from "../../migration-config.js";
import { import {
createMigration, AstContentMigrateAction,
MigrateAction, createContentMigration,
MigrationContext, MigrationContext,
TypeSpecCompilerV0_37, MigrationKind,
} from "../migration.js"; } from "../../migration-types.js";
export const migrateModelToScalar = createMigration({ export const migrateModelToScalar = createContentMigration({
name: "Migrate Model To scalar", name: "Migrate Model To scalar",
kind: "Syntax", kind: MigrationKind.AstContentMigration,
from: "0.37", from: "0.37.0",
to: "0.38", to: "0.38.0",
migrate: ( migrate: (
{ printNode, printNodes }: MigrationContext, { printNode, printNodes }: MigrationContext,
compilerV37: TypeSpecCompilerV0_37, compilerV37: TypeSpecCompilerV0_37,
@ -27,7 +28,7 @@ export const migrateModelToScalar = createMigration({
return `<${parameters.map((x) => printNode(x)).join(", ")}>`; return `<${parameters.map((x) => printNode(x)).join(", ")}>`;
} }
const actions: MigrateAction[] = []; const actions: AstContentMigrateAction[] = [];
visitRecursive(compilerV37, root, (node) => { visitRecursive(compilerV37, root, (node) => {
if ( if (
node.kind === compilerV37.SyntaxKind.ModelStatement && node.kind === compilerV37.SyntaxKind.ModelStatement &&
@ -39,6 +40,7 @@ export const migrateModelToScalar = createMigration({
) { ) {
const decorators = printNodes(node.decorators); const decorators = printNodes(node.decorators);
actions.push({ actions.push({
kind: MigrationKind.AstContentMigration,
target: node, target: node,
content: `${decorators ? decorators + " " : ""}scalar ${ content: `${decorators ? decorators + " " : ""}scalar ${
node.id.sv node.id.sv

273
packages/migrate/src/migrations/v0.41/typespec-rename.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1,273 @@
import type { Node, TypeSpecScriptNode } from "@typespec/compiler";
import { getAnyExtensionFromPath, NodePackage } from "@typespec/compiler";
import { readFile } from "fs/promises";
import * as yaml from "js-yaml";
import * as path from "path";
import type { TypeSpecCompilerV0_40 } from "../../migration-config.js";
import {
AstContentMigrateAction,
createContentMigration,
createFileContentMigration,
createFileRenameMigration,
createPackageVersionMigration,
FileContentMigrationAction,
FileRenameAction,
MigrationContext,
MigrationKind,
PackageVersionUpdateAction,
} from "../../migration-types.js";
export const updatePackageVersion = createPackageVersionMigration({
name: "Update package version",
kind: MigrationKind.PackageVersionUpdate,
migrate: (pkg: NodePackage) => {
const actions: Array<PackageVersionUpdateAction> = [];
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/compiler",
renamePackageName: "@typespec/compiler",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/openapi",
renamePackageName: "@typespec/openapi",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/openapi3",
renamePackageName: "@typespec/openapi3",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/http",
renamePackageName: "@typespec/http",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/versioning",
renamePackageName: "@typespec/versioning",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/rest",
renamePackageName: "@typespec/rest",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@cadl-lang/lint",
renamePackageName: "@typespec/lint",
toVersion: "0.41.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-autorest",
renamePackageName: "@azure-tools/typespec-autorest",
toVersion: "0.27.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-azure-core",
renamePackageName: "@azure-tools/typespec-azure-core",
toVersion: "0.27.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-azure-resource-manager",
renamePackageName: "@azure-tools/typespec-azure-resource-manager",
toVersion: "0.27.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-dpg",
renamePackageName: "@azure-tools/typespec-client-generator-core",
toVersion: "0.27.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-providerhub",
renamePackageName: "@azure-tools/typespec-providerhub",
toVersion: "0.27.0",
});
actions.push({
kind: MigrationKind.PackageVersionUpdate,
packageName: "@azure-tools/cadl-providerhub-controller",
renamePackageName: "@azure-tools/typespec-providerhub-controller",
toVersion: "0.27.0",
});
return actions;
},
});
export const migrateCadlNameToTypeSpec = createContentMigration({
name: "Migrate Model To scalar",
kind: MigrationKind.AstContentMigration,
from: "0.40.0",
to: "0.41.0",
migrate: (
{ printNode, printNodes }: MigrationContext,
compilerV40: TypeSpecCompilerV0_40,
root: TypeSpecScriptNode
) => {
const actions: AstContentMigrateAction[] = [];
visitRecursive(compilerV40, root, (node) => {
if (node.kind === compilerV40.SyntaxKind.ImportStatement && node.path.value.length > 0) {
let newContent = "";
if (node.path.value.includes("/cadl-dpg")) {
newContent = node.path.value.replace("/cadl-dpg", "/typespec-client-generator-core");
} else if (node.path.value.includes("@cadl-lang")) {
newContent = node.path.value.replace("@cadl-lang", "@typespec");
} else if (node.path.value.includes("@azure-tools/cadl")) {
newContent = node.path.value.replace("@azure-tools/cadl", "@azure-tools/typespec");
}
if (newContent.length > 0) {
actions.push({
kind: MigrationKind.AstContentMigration,
target: node,
content: `import "${newContent}";`,
});
}
} else if (
node.kind === compilerV40.SyntaxKind.UsingStatement &&
node.name !== undefined &&
node.name.kind === compilerV40.SyntaxKind.MemberExpression
) {
if (node.name.id.sv === "DPG") {
actions.push({
kind: MigrationKind.AstContentMigration,
target: node.name,
content: `Azure.ClientGenerator.Core`,
});
}
if (
node.name.base !== undefined &&
node.name.base.kind === compilerV40.SyntaxKind.Identifier &&
node.name.base.sv === "Cadl"
) {
actions.push({
kind: MigrationKind.AstContentMigration,
target: node.name.base,
content: `TypeSpec`,
});
}
}
});
return actions;
},
});
export const renameCadlFileNames = createFileRenameMigration({
name: "Rename cadl file names",
kind: MigrationKind.FileRename,
migrate: (fileNames: string[]) => {
const actions: Array<FileRenameAction> = [];
for (let i = 0; i < fileNames.length; i++) {
let toName: string | undefined = undefined;
const pathOnly = path.dirname(fileNames[i]);
const fileName = path.basename(fileNames[i]);
if (fileName === "cadl-project.yaml") {
toName = "tspconfig.yaml";
}
if (getAnyExtensionFromPath(fileName) === ".cadl") {
toName = fileName.slice(0, fileName.lastIndexOf(".")) + ".tsp";
}
if (toName !== undefined) {
actions.push({
kind: MigrationKind.FileRename,
sourceFileName: fileNames[i],
targetFileName: path.join(pathOnly, toName),
});
}
}
return actions;
},
});
export const migrateTspConfigFile = createFileContentMigration({
name: "Migrate cadl-project.yaml and tspConfig.yaml",
kind: MigrationKind.FileContentMigration,
migrate: async (fileNames: string[]) => {
// Old cadl-project.yaml file would have been migrated already.
// So we only need to deal with new config file name.
const TspConfigFileName = "tspconfig.yaml";
const actions: Array<FileContentMigrationAction> = [];
for (let i = 0; i < fileNames.length; i++) {
const fileName = path.basename(fileNames[i]);
if (fileName === TspConfigFileName) {
// loading content
const buffer = await readFile(fileName);
let content = buffer.toString();
// replacing cadl with typespec
const replaceKeys = Object.keys(CadlToTypeSpecReplacement);
for (const key of replaceKeys) {
content = content.replace(key, CadlToTypeSpecReplacement[key]);
}
// load data & convert to new format if needed to
let tspConfig: any;
try {
tspConfig = yaml.load(content);
// if config has older deprecated emitters format, convert to new format
if (tspConfig?.emitters !== undefined) {
(tspConfig as { emit: Array<string> }).emit = [];
(tspConfig as { options: Record<string, any> }).options = {};
// convert each emitters to new emit format
for (const key in tspConfig.emitters) {
tspConfig.emit.push(key);
if (typeof tspConfig.emitters[key] !== "boolean") {
tspConfig.options[key] = tspConfig.emitters[key];
}
}
// clean up config object for minimal output
tspConfig.emitters = undefined;
if (tspConfig.options.length === 0) tspConfig.options = undefined;
content = yaml.dump(tspConfig);
}
} catch (err) {
console.warn(
`Failed to load ${fileNames[i]}. File may not have been migrated correctly. Error details: ${err}`
);
}
// Create replacement action
actions.push({
kind: MigrationKind.FileContentMigration,
fileName: fileNames[i],
newContent: content,
});
}
}
return actions;
},
});
function visitRecursive(compiler: any, root: Node, callback: (node: Node) => void) {
const visit = (node: Node) => {
callback(node);
compiler.visitChildren(node, visit);
};
visit(root);
}
const CadlToTypeSpecReplacement: { [key: string]: string } = {
"@cadl-lang/": "@typespec/",
"@azure-tools/cadl-": "@azure-tools/typespec-",
};

Просмотреть файл

@ -2,7 +2,15 @@ import { globby } from "globby";
import { join } from "path"; import { join } from "path";
export async function findTypeSpecFiles(root: string, ignore: string[] = []) { export async function findTypeSpecFiles(root: string, ignore: string[] = []) {
return findFiles([normalizePath(join(root, "**/*.tsp"))], ignore); return findFiles(
[
normalizePath(join(root, "**/*.tsp")),
normalizePath(join(root, "**/*.cadl")),
normalizePath(join(root, "**/cadl-project.yaml")),
normalizePath(join(root, "**/tspconfig.yaml")),
],
ignore
);
} }
export async function findFiles(include: string[], ignore: string[] = []): Promise<string[]> { export async function findFiles(include: string[], ignore: string[] = []): Promise<string[]> {

Просмотреть файл

@ -1,5 +1,5 @@
import { strictEqual } from "assert"; import { strictEqual } from "assert";
import { migrateTypeSpecContent } from "../src/migrate.js"; import { migrateTypeSpecContent } from "../src/migration-impl.js";
import { migrateModelToScalar } from "../src/migrations/v0.38/model-to-scalars.js"; import { migrateModelToScalar } from "../src/migrations/v0.38/model-to-scalars.js";
describe("migration: model to scalars", () => { describe("migration: model to scalars", () => {

3
packages/migrate/test/scenarios/0.37/cadl-project.yaml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
emitters:
"@azure-tools/cadl-autorest":
output-file: test.json

95
packages/migrate/test/scenarios/0.37/main.cadl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,95 @@
import "@cadl-lang/rest";
import "@cadl-lang/openapi";
import "@azure-tools/cadl-autorest";
import "@azure-tools/cadl-azure-core";
import "@azure-tools/cadl-azure-resource-manager";
import "@azure-tools/cadl-dpg";
// See here for more information: https://aka.ms/cadl/learn
using Autorest;
using Azure.ResourceManager;
using Cadl.Http;
using Cadl.Rest;
using Cadl.Versioning;
using Azure.DPG;
using OpenAPI;
@armProviderNamespace
@service({
title: "IndexManagementClient",
version: "2022-06-01-preview",
})
@doc("Microsoft.Search resource management API.")
@versionedDependency(Azure.ResourceManager.Versions.v1_0_Preview_1)
namespace Microsoft.Search;
interface Operations extends Azure.ResourceManager.Operations {}
@doc("An index resource.")
model Index is TrackedResource<IndexProperties> {
@path
@key("name")
@segment("searchIndexes")
@visibility("read")
@doc("The name of the index resource.")
name: string;
}
@armResourceOperations
interface IndexOperations extends ResourceOperations<Index, IndexProperties> {}
@doc("The properties of the index.")
model IndexProperties {
@visibility("read")
@doc("The current provisioning state of the index.")
provisioningState?: ProvisioningState;
@visibility("read")
@doc("The endpoint at which the index can be accessed.")
endpoint?: string;
@doc("The capacity allocated to the index for querying.")
queryCapacity: Capacity;
@doc("The capacity allocated to the index for indexing documents.")
indexingCapacity: Capacity;
}
@doc("The current provisioning state of the index.")
enum ProvisioningState {
Accepted,
Provisioning,
Succeeded,
Failed,
Canceled,
Deleting,
}
@doc("The capacity will autoscale between the minimum and maximum number of vCores based on the usage of your index.")
model Capacity {
@doc("The minimum number of vCores that the index will consume. Represented with discrete values: 0.2, 0.5. 1, 2, 3, … to 16.")
minVCores: float32;
@doc("The maximum number of vCores that the index can consume. Represented with discrete values: 0.2, 0.5. 1, 2, 3, … to 16.")
maxVCores: float32;
autoPause: Pause;
}
@doc("Index pause strategy")
@discriminator("type")
model Pause {}
@doc("When the pause strategy is set to 'Delay', the index will enter a paused state after not being used for a fixed amount of time.")
model DelayPause extends Pause {
@doc("Specifies the type of pausing strategy as 'Delay'.")
type: "Delay";
@doc("The interval after which an index is paused if not in use.")
duration: duration;
}
@doc("When the pause strategy is set to 'None', the index will remain always active.")
model NonePause extends Pause {
@doc("Specifies the type of pausing strategy as 'None'.")
type: "None";
}

21
packages/migrate/test/scenarios/0.37/package.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
{
"name": "Microsoft.Search",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"build": "echo \"Nothing to do for template.\""
},
"dependencies": {
"@azure-tools/cadl-autorest": "0.22.0",
"@azure-tools/cadl-azure-core": "0.9.0",
"@azure-tools/cadl-azure-resource-manager": "0.12.0",
"@azure-tools/cadl-dpg": "0.3.0",
"@cadl-lang/openapi": "0.14.0",
"@cadl-lang/rest": "0.19.0",
"@cadl-lang/versioning": "0.10.0"
},
"devDependencies": {
"@cadl-lang/compiler": "0.37.0"
}
}

Просмотреть файл

@ -8,7 +8,8 @@
"outDir": "dist", "outDir": "dist",
"rootDir": ".", "rootDir": ".",
"tsBuildInfoFile": "temp/tsconfig.tsbuildinfo", "tsBuildInfoFile": "temp/tsconfig.tsbuildinfo",
"types": ["node", "mocha"] "types": ["node", "mocha"],
"resolveJsonModule": true
}, },
"include": ["src/**/*.ts", "test/**/*.ts"] "include": ["src/**/*.ts", "test/**/*.ts"]
} }