refactor-modular-code-a-little-and-add-unit-test-for-it (#1989)

* refactor-modular-code-a-little-and-add-unit-test-for-it

* fix format

* fix ci

* replace all possible cadl with typespec

* rename other files

* fix format
This commit is contained in:
Qiaoqiao Zhang 2023-08-28 09:38:03 +08:00 коммит произвёл GitHub
Родитель d350fb2ecc
Коммит 62cd637045
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
99 изменённых файлов: 818 добавлений и 706 удалений

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

@ -14,8 +14,8 @@ parameters:
variables:
AUTOREST_TESTSERVER_COVERAGE_DIRECTORY: "$(Build.SourcesDirectory)/packages/autorest.typescript/coverage/"
CADL_TESTSERVER_COVERAGE_RLC_REPORT: "$(Build.SourcesDirectory)/packages/typespec-ts/coverage/cadl-ranch-coverage-typescript-rlc.json"
CADL_TESTSERVER_COVERAGE_MODULAR_REPORT: "$(Build.SourcesDirectory)/packages/typespec-ts/coverage/cadl-ranch-coverage-typescript-modular.json"
TypeSpec_TESTSERVER_COVERAGE_RLC_REPORT: "$(Build.SourcesDirectory)/packages/typespec-ts/coverage/cadl-ranch-coverage-typescript-rlc.json"
TypeSpec_TESTSERVER_COVERAGE_MODULAR_REPORT: "$(Build.SourcesDirectory)/packages/typespec-ts/coverage/cadl-ranch-coverage-typescript-modular.json"
pool:
vmImage: ubuntu-20.04
@ -220,7 +220,7 @@ stages:
name: SmokeTest_RLC
tag: ci_rlc
- job: Cadl_Smoke_Test
- job: TypeSpec_Smoke_Test
dependsOn: Build
variables:
- template: globals.yml
@ -245,7 +245,7 @@ stages:
- template: build.yml
- script: node $(Build.SourcesDirectory)/common/scripts/install-run-rushx.js smoke-test
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-test
displayName: "Generate Code From Cadl"
displayName: "Generate Code From TypeSpec"
- script: npm run check:tree
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-test
displayName: "Check git Tree"
@ -278,25 +278,25 @@ stages:
displayName: "Lint check for rlc common lib"
- script: npm run lint
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
displayName: "Lint check for Cadl emitter"
displayName: "Lint check for TypeSpec emitter"
- script: npm run check-format
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
displayName: "Format check for Cadl emitter"
displayName: "Format check for TypeSpec emitter"
- script: npm run test
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
displayName: "Generate RLC Test Clients from Cadl-ranch"
- script: npm run check:tree
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
displayName: "Check git Tree"
- script: npx cadl-ranch check-coverage ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFiles $(CADL_TESTSERVER_COVERAGE_RLC_REPORT) --coverageFiles $(CADL_TESTSERVER_COVERAGE_MODULAR_REPORT)
- script: npx cadl-ranch check-coverage ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFiles $(TypeSpec_TESTSERVER_COVERAGE_RLC_REPORT) --coverageFiles $(TypeSpec_TESTSERVER_COVERAGE_MODULAR_REPORT)
displayName: "Check Coverage"
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
continueOnError: true
- publish: $(CADL_TESTSERVER_COVERAGE_RLC_REPORT)
- publish: $(TypeSpec_TESTSERVER_COVERAGE_RLC_REPORT)
artifact: RLCCoverageReport
displayName: "Publish rlc coverage report"
condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'internal'), eq( variables['Agent.OS'], 'Linux'))
- publish: $(CADL_TESTSERVER_COVERAGE_MODULAR_REPORT)
- publish: $(TypeSpec_TESTSERVER_COVERAGE_MODULAR_REPORT)
artifact: ModularCoverageReport
displayName: "Publish modular coverage report"
condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'internal'), eq( variables['Agent.OS'], 'Linux'))
@ -309,8 +309,8 @@ stages:
scriptLocation: "inlineScript"
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-ts
inlineScript: |
npx cadl-ranch upload-coverage --coverageFile $(CADL_TESTSERVER_COVERAGE_RLC_REPORT) --generatorName typescript/rlc --storageAccountName azuresdkcadlranch --generatorVersion $(node -p -e "require('./package.json').version")
npx cadl-ranch upload-coverage --coverageFile $(CADL_TESTSERVER_COVERAGE_MODULAR_REPORT) --generatorName typescript/modular --storageAccountName azuresdkcadlranch --generatorVersion $(node -p -e "require('./package.json').version")
npx cadl-ranch upload-coverage --coverageFile $(TypeSpec_TESTSERVER_COVERAGE_RLC_REPORT) --generatorName typescript/rlc --storageAccountName azuresdkcadlranch --generatorVersion $(node -p -e "require('./package.json').version")
npx cadl-ranch upload-coverage --coverageFile $(TypeSpec_TESTSERVER_COVERAGE_MODULAR_REPORT) --generatorName typescript/modular --storageAccountName azuresdkcadlranch --generatorVersion $(node -p -e "require('./package.json').version")
# The Prerelease and Release stages are conditioned on whether we are building a pull request and the branch.
- ${{if and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'internal'), eq(parameters.IncludeRelease,true))}}:

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

@ -27,4 +27,4 @@ stages:
- template: nightly-prepare.yml
- script: node $(Build.SourcesDirectory)/common/scripts/install-run-rushx.js smoke-test
workingDirectory: $(Build.SourcesDirectory)/packages/typespec-test
displayName: "Generate Code From Cadl"
displayName: "Generate Code From TypeSpec"

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

@ -278,12 +278,12 @@ stages:
npm publish $(TAR_NAME) --access public --tag dev
npm config delete //registry.npmjs.org/:_authToken
displayName: "Publish @autorest/typescript to NPM"
- deployment: PublishCadlAutorestToNpm
- deployment: PublishTypeSpecTSToNpm
condition: or(eq(variables['SetDevVersion'], 'true'), and(eq(variables['SetDevVersion'], ''), eq(variables['Build.Reason'],'Schedule'), eq(variables['System.TeamProject'], 'internal')))
variables:
TAR_NAME: $[ stageDependencies.BuildStage.Build.outputs['PackTypeSpecTSArtifacts.TAR_NAME'] ]
environment: npmtsjssdk
displayName: Publish @azure-tools/cadl-autorest dev version to NPM
displayName: Publish @azure-tools/typespec-ts dev version to NPM
pool:
name: ${{ parameters.LinuxPool }}
vmImage: ${{ parameters.OSVmImage }}

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

@ -44,7 +44,7 @@ In order contribute to this project, You will need to install some prerequisite
- Rush will automatically manage the specific version needed by this repo as long as you have any v5 version installed.
- If you're unable to install a global tool, you can instead call the wrapper script `node <repo root>/common/scripts/install-run-rush.js` any time the guide instructs you to run `rush`. The wrapper script will install a managed copy of Rush in a temporary directory for you.
- [Autorest](https://www.npmjs.com/package/autorest), if you're planning contribute to the generator code from swagger either for high level client or for rest level client.
- [Cadl Compiler](https://www.npmjs.com/package/@cadl-lang/compiler), if you're planning contribute to the generator code from cadl.
- [TypeSpec Compiler](https://www.npmjs.com/package/@typespec/compiler), if you're planning contribute to the generator code from TypeSpec.
### Things to keep in mind when contributing

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

@ -7,14 +7,14 @@ This repository is the code generator libraries for Azure TypeScript SDK and Azu
| Name | Changelog | Latest | Next |
| --------------------------------------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [@autorest/typescript][autorest_typescript_src] | [Changelog][autorest_typescript_chg] | [![](https://img.shields.io/npm/v/@autorest/typescript)](https://www.npmjs.com/package/@autorest/typescript) | ![](https://img.shields.io/npm/v/@autorest/typescript/next) |
| [@azure-tools/cadl-typescript][cadl-typescript_src] | [Changelog][cadl-typescript_chg] | [![](https://img.shields.io/npm/v/@azure-tools/cadl-typescript)](https://www.npmjs.com/package/@azure-tools/cadl-typescript) | ![](https://img.shields.io/npm/@azure-tools/cadl-azure-core/next) |
| [@azure-tools/typespec-ts][typespec-ts_src] | [Changelog][typespec-ts_chg] | [![](https://img.shields.io/npm/v/@azure-tools/typespec-ts)](https://www.npmjs.com/package/@azure-tools/typespec-ts) | ![](https://img.shields.io/npm/@azure-tools/typespec-azure-core/next) |
| [@azure-tools/rlc-common][rlc-common_src] | [Changelog][rlc-common_chg] | [![](https://img.shields.io/npm/v/@azure-tools/rlc-common)](https://www.npmjs.com/package/@azure-tools/rlc-common) | ![](https://img.shields.io/npm/@azure-tools/rlc-common/next) |
[autorest_typescript_src]: packages/autorest.typescript/
[autorest_typescript_chg]: packages/autorest.typescript/CHANGELOG.md
[cadl-typescript_src]: packages/cadl-typescript
[cadl-typescript_chg]: packages/cadl-typescript/CHANGELOG.md
[typespec-ts_src]: packages/typespec-ts
[typespec-ts_chg]: packages/typespec-ts/CHANGELOG.md
[rlc-common_src]: packages/rlc-common
[rlc-common_chg]: packages/rlc-common/CHANGELOG.md
@ -23,8 +23,8 @@ This repository is the code generator libraries for Azure TypeScript SDK and Azu
### General Introduction
Inside this project, we support both high level client generation and rest level client generation. In the rest level client generation, we support generate code from both rest api specs and cadl. In the high level client generation, we only support generation from rest api specs.
Inside this project, we support both high level client generation and rest level client generation. In the rest level client generation, we support generate code from both rest api specs and typespec. In the high level client generation, we only support generation from rest api specs.
- [**@autorest/typescript:**](https://github.com/Azure/autorest.typescript/tree/main/packages/autorest.typescript) contains the original high level client generation and the rest level client generation, mostly including the transformation from autorest code model into RLC model part.
- [**@azure-tools/cadl-typescript:**](https://github.com/Azure/autorest.typescript/tree/main/packages/cadl-typescript) is the typescript cadl emitter, which contains the transformation from cadl model into RLC model.
- [**@azure-tools/rlc-common:**](https://github.com/Azure/autorest.typescript/tree/main/packages/rlc-common) contains the common generation logic from RLC model into rest client libraries code part. Which is depended by both `@autorest/typescript` rlc generation part and `@azure-tools/cadl-typescript`.
- [**@azure-tools/typespec-ts:**](https://github.com/Azure/autorest.typescript/tree/main/packages/typespec-ts) is the typescript TypeSpec emitter, which contains the transformation from TypeSpec model into RLC model.
- [**@azure-tools/rlc-common:**](https://github.com/Azure/autorest.typescript/tree/main/packages/rlc-common) contains the common generation logic from RLC model into rest client libraries code part. Which is depended by both `@autorest/typescript` rlc generation part and `@azure-tools/typespec-ts`.

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

@ -2,7 +2,7 @@
## Overview
In the JavaScript/TypeScript RLC generator, we support generate RLC code from both CADL input and Swagger input. This document will mainly talk about how the high level design of JavaScript/TypeScript Rest Level Client (RLC) generator looks like. we will first show the whole workflow and then introduce the RLC generation from CADL and Swagger separately.
In the JavaScript/TypeScript RLC generator, we support generate RLC code from both TypeSpec input and Swagger input. This document will mainly talk about how the high level design of JavaScript/TypeScript Rest Level Client (RLC) generator looks like. we will first show the whole workflow and then introduce the RLC generation from TypeSpec and Swagger separately.
## Overall Workflow
@ -10,10 +10,10 @@ Basically, the whole workflow is shown in the below flowchart.
```mermaid
graph TD
A[CADL Files] -->|CADL compiler| B(CADL Program)
B -->|CADL TypeScript emitter| C{RLCModel}
A[TypeSpec Files] -->|TypeSpec compiler| B(TypeSpec Program)
B -->|TypeSpec TypeScript emitter| C{RLCModel}
C --> |RLC common| D{RLC File Content}
D --> |CADL TypeScript emitter| E(JS RLC Code)
D --> |TypeSpec TypeScript emitter| E(JS RLC Code)
F(Swager Files) -->|Autorest core & m4 plugin| G(Modelerfour)
G -->|Autotest TypeScript Plugin| C
D --> |Autorest TypeScript Plugin| E
@ -23,30 +23,30 @@ D --> |Autorest TypeScript Plugin| E
To better understand the above flowchart, we list some basic terms here.
- **Cadl Files**: A Service API that is defined using the [CADL](https://github.com/microsoft/cadl) language.
- **TypeSpec Files**: A Service API that is defined using the [TypeSpec](https://github.com/microsoft/typespec) language.
- **Swagger Files**: A REST api specification that follows the [OpenAPI](https://swagger.io/) definition.
- **CADL Program**: An internal model that is provided after CADL compiler has processed the CADL input.
- **TypeSpec Program**: An internal model that is provided after TypeSpec compiler has processed the TypeSpec input.
- **Modelerfour**: A code model that is provided after Autorest core and Modelerfour plugin have processed the swagger input.
- **RLCModel**: An internally defined model that contains all the necessary information required to build the RLC file content.
- **CADL compiler**: A module that compiles the CADL input and provides a set of APIs to the CADL emitter to retrieve the CADL program model.
- **TypeSpec compiler**: A module that compiles the TypeSpec input and provides a set of APIs to the TypeSpec emitter to retrieve the TypeSpec program model.
- **Autorest core & m4 plugin**: A module that takes swagger files as input and outputs the code model Modelerfour.
- **CADL TypeScript emitter**: A module that transforms the CADL program into RLCModel.
- **TypeSpec TypeScript emitter**: A module that transforms the TypeSpec program into RLCModel.
- **RLC common**: A common part that takes RLCModel as input and builds the RLC file content.
- **Autorest TypeScript plugin**: A module that transforms the Modelerfour into RLCModel.
## RLC generation from CADL
## RLC generation from TypeSpec
On a high level, the RLC generation process from CADL input involves the following steps:
1. The CADL input is processed by the CADL compiler to generate a CADL program model.
1. The CADL program model is transformed into an RLCModel.
On a high level, the RLC generation process from TypeSpec input involves the following steps:
1. The TypeSpec input is processed by the TypeSpec compiler to generate a TypeSpec program model.
1. The TypeSpec program model is transformed into an RLCModel.
1. The RLCModel is passed to the RLC Common library, which generates the code for the RLC file.
```mermaid
graph TD
A[CADL Files] -->|CADL compiler| B(CADL Program)
B -->|CADL TypeScript emitter| C{RLCModel}
A[TypeSpec Files] -->|TypeSpec compiler| B(TypeSpec Program)
B -->|TypeSpec TypeScript emitter| C{RLCModel}
C --> |RLC common| D(RLC File Content)
D --> |CADL TypeScript emitter| E(JS RLC Code)
D --> |TypeSpec TypeScript emitter| E(JS RLC Code)
```
## RLC generation from Swagger

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

@ -1,6 +1,6 @@
# Contributing
we have a [interfaces.ts](./src/interfaces.ts) to define the RLCModel And RLCOptions that is export for both Autorest RLC generator and Cadl emitters.
we have a [interfaces.ts](./src/interfaces.ts) to define the RLCModel And RLCOptions that is export for both Autorest RLC generator and TypeSpec emitters.
The generated Typescript/Javascript Rest Level Client has the following structure:

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

@ -1,3 +1,3 @@
# Introduction
In this library, we abstract the common generation logic for RLC generation from both swaggers and cadl. In this way, the autorest.typescript part will only need to transform the code model into RLCModel, and the cadl emitter will only need to transform the cadl program into RLCModel, then the rlc-common library will take the rest generation part to build the file content of from the RLCModel.
In this library, we abstract the common generation logic for RLC generation from both swaggers and typespec. In this way, the autorest.typescript part will only need to transform the code model into RLCModel, and the TypeSpec emitter will only need to transform the TypeSpec program into RLCModel, then the rlc-common library will take the rest generation part to build the file content of from the RLCModel.

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

@ -135,13 +135,13 @@ export interface RLCOptions {
generateSample?: boolean;
azureSdkForJs?: boolean;
azureOutputDirectory?: string;
isCadlTest?: boolean;
isTypeSpecTest?: boolean;
title?: string;
dependencyInfo?: DependencyInfo;
productDocLink?: string;
serviceInfo?: ServiceInfo;
azureArm?: boolean;
sourceFrom?: "Cadl" | "Swagger";
sourceFrom?: "TypeSpec" | "Swagger";
isModularLibrary?: boolean;
enableOperationGroup?: boolean;
}

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

@ -55,7 +55,7 @@ function restLevelPackage(model: RLCModel, hasSamplesGenerated: boolean) {
generateSample,
azureOutputDirectory,
azureSdkForJs,
isCadlTest,
isTypeSpecTest,
sourceFrom,
multiClient,
batch
@ -228,7 +228,7 @@ function restLevelPackage(model: RLCModel, hasSamplesGenerated: boolean) {
packageInfo.devDependencies["uglify-js"] = "^3.4.9";
}
if (isCadlTest) {
if (isTypeSpecTest) {
packageInfo["type"] = "module";
}

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

@ -235,14 +235,14 @@ model SwapDeploymentsParams {
}
interface Projects {
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Creates a new project or updates an existing one.")
createOrUpdate is LongRunningResourceCreateOrUpdate<Project>;
@doc("Gets the details of a project.")
get is ResourceRead<Project>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Deletes a project.")
delete is LongRunningResourceDelete<Project>;
@ -254,7 +254,7 @@ interface Projects {
}
>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Triggers a job to export a project's data.")
export is ResourceAction<
Project,
@ -262,7 +262,7 @@ interface Projects {
TypeSpec.Http.AcceptedResponse & Foundations.LongRunningStatusLocation
>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
// NOTE: `import` is a reserved keyword
@doc("Triggers a job to export a project's data.")
importx is ResourceAction<
@ -271,7 +271,7 @@ interface Projects {
TypeSpec.Http.AcceptedResponse & Foundations.LongRunningStatusLocation
>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Triggers a training job for a project.")
train is ResourceAction<
Project,
@ -288,18 +288,18 @@ interface Deployments {
@doc("Gets the details of a deployment.")
getDeployment is ResourceRead<Deployment>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Creates a new deployment or replaces an existing one.")
deployProject is LongRunningResourceCreateOrReplace<Deployment>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Deletes a project deployment.")
deleteDeployment is LongRunningResourceDelete<Deployment>;
@doc("Lists the existing deployments.")
listDeployments is ResourceList<Deployment>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Swaps two existing deployments with each other.")
@collectionAction(Deployment, "swap")
swapDeployments is ResourceCollectionAction<
@ -319,13 +319,13 @@ interface Jobs {
@route("projects/global/")
interface Global {
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service that cannot be changed."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service that cannot be changed."
@get
@route("languages")
@doc("Gets the supported languages.")
getSupportedLanguages is Foundations.Operation<StandardListQueryParameters, SupportedLanguages>;
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service that cannot be changed."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service that cannot be changed."
@get
@doc("Lists training configuration versions.")
@route("training-config-versions")

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

@ -528,7 +528,7 @@ model ApplicationListResult {
@items
value?: Application[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -591,7 +591,7 @@ model PoolListUsageMetricsResult {
@items
value?: PoolUsageMetrics[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -630,7 +630,7 @@ model AccountListSupportedImagesResult {
@items
value?: ImageInformation[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -642,7 +642,7 @@ information about the Image.
""")
@resource("supportedimages")
model ImageInformation {
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The ID of the Compute Node agent SKU which the Image supports.")
// FIXME: (resource-key-guessing) - Verify that this property is the resource key, if not please update the model with the right one
@visibility("read")

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

@ -531,7 +531,7 @@ model ApplicationListResult {
@items
value?: Application[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -594,7 +594,7 @@ model PoolListUsageMetricsResult {
@items
value?: PoolUsageMetrics[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -633,7 +633,7 @@ model AccountListSupportedImagesResult {
@items
value?: ImageInformation[];
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The URL to get the next set of results.")
@nextLink
"odata.nextLink"?: string;
@ -645,7 +645,7 @@ information about the Image.
""")
@resource("supportedimages")
model ImageInformation {
#suppress "@azure-tools/cadl-azure-core/casing-style" "The names of Property types must use camelCase"
#suppress "@azure-tools/typespec-azure-core/casing-style" "The names of Property types must use camelCase"
@doc("The ID of the Compute Node agent SKU which the Image supports.")
// FIXME: (resource-key-guessing) - Verify that this property is the resource key, if not please update the model with the right one
@visibility("read")

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

@ -168,13 +168,13 @@ model PagedLedgerEntries {
@route("/app")
namespace ConfidentialLedger {
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
@summary("Retrieves a list of collection ids present in the Confidential Ledger")
@doc("Collection ids are user-created collections of ledger entries")
op listCollections is Azure.Core.Foundations.NonPagedResourceList<Collection>;
// TODO: add return model
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
@route("/enclaveQuotes")
@summary("Gets quotes for all nodes of the Confidential Ledger.")
@doc("A quote is an SGX enclave measurement that can be used to verify the validity of a node and its enclave.")
@ -182,7 +182,7 @@ namespace ConfidentialLedger {
op getEnclaveQuotes is Azure.Core.Foundations.Operation<{}, OkResponse>;
// TODO: add return model
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
@route("/governance/constitution")
@summary("Gets the constitution used for governance.")
@doc("The constitution is a script that assesses and applies proposals from consortium members.")
@ -190,14 +190,14 @@ namespace ConfidentialLedger {
op getConstitution is Azure.Core.Foundations.Operation<{}, OkResponse>;
// TODO: add return model
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service, we have a non-conforming operation."
@route("/governance/members")
@summary("Gets the consortium members.")
@doc("Consortium members can manage the Confidential Ledger.")
@get
op getConsortiumMembers is Azure.Core.Foundations.Operation<{}, OkResponse>;
#suppress "@azure-tools/cadl-azure-core/use-standard-operations" "This is an existing service with a non-standard list operation."
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "This is an existing service with a non-standard list operation."
@summary("Gets ledger entries from a collection corresponding to a range.")
@doc("A collection id may optionally be specified. Only entries in the specified (or default) collection will be returned.")
op listLedgerEntries is Azure.Core.Foundations.ResourceList<LedgerEntry, {}, PagedLedgerEntries>;

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

@ -6,7 +6,7 @@ using Azure.Core.Foundations;
namespace Azure.Core.Foundations.Extensions;
/*
This CADL file was created to customize the existing implementation from the foundations library.
This TypeSpec file was created to customize the existing implementation from the foundations library.
In this file we have addressed the following issues:
1. Avoid inlining of the models - required by ADP backend and also by the AutoRest. All models must be references and have schema definitions in the OpenApi spec.
2. In ADP we are using slightly different model for LRO. It has additional state [Created] and the operation type property.

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

@ -66,7 +66,7 @@ interface Deployments {
@doc("Gets the details of a deployment.")
getDeployment is ResourceRead<Deployment>;
#suppress "@azure-tools/cadl-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "This operation does not follow the standard long-running operation pattern."
@doc("Creates a new deployment or replaces an existing one.")
deployProject is CustomResourceCreateOrReplace<
Deployment,

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

@ -1,31 +1,31 @@
emit: [
# "@azure-tools/typespec-csharp",
# "@azure-tools/cadl-python",
# "@azure-tools/typespec-java",
"@azure-tools/typespec-ts",
]
# "@azure-tools/typespec-csharp",
# "@azure-tools/typespec-python",
# "@azure-tools/typespec-java",
'@azure-tools/typespec-ts',
]
options:
# "@azure-tools/typespec-csharp":
# namespace : "Azure.Health.Insights.ClinicalMatching"
# clear-output-folder : true
# new-project : false
# model-namespace : false
# "@azure-tools/typespec-java":
# namespace: "Com.Azure.Health.Insights.ClinicalMatching"
# clear-output-folder: true
# new-project: false
# model-namespace: false
# "@azure-tools/cadl-python":
# package-mode: "dataplane"
# package-name: "azure-healthinsights-clinicalmatching"
"@azure-tools/typespec-ts":
title: Health Insights Clinical Matching
generateMetadata: true
generateTest: true
azureSdkForJs: false
"emitter-output-dir": "{project-root}/generated/typespec-ts"
packageDetails:
name: "@azure-rest/health-insights-clinicalmatching"
description: "Azure Health Insights ClinicalMatching"
version: "1.0.0-beta.1"
# "@azure-tools/typespec-csharp":
# namespace : "Azure.Health.Insights.ClinicalMatching"
# clear-output-folder : true
# new-project : false
# model-namespace : false
# "@azure-tools/typespec-java":
# namespace: "Com.Azure.Health.Insights.ClinicalMatching"
# clear-output-folder: true
# new-project: false
# model-namespace: false
# "@azure-tools/typespec-python":
# package-mode: "dataplane"
# package-name: "azure-healthinsights-clinicalmatching"
'@azure-tools/typespec-ts':
title: Health Insights Clinical Matching
generateMetadata: true
generateTest: true
azureSdkForJs: false
'emitter-output-dir': '{project-root}/generated/typespec-ts'
packageDetails:
name: '@azure-rest/health-insights-clinicalmatching'
description: 'Azure Health Insights ClinicalMatching'
version: '1.0.0-beta.1'

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

@ -34,7 +34,7 @@ npm run test
Running the command above will do the following things:
- Start TestServer
- Build Cadl Typescript
- Build TypeSpec TS
- Generate all scenarios in parallel (i.e. Dictionary, Extensible Enums, Models, Resiliency)
- Run all the tests under test/integration
- Stop TestServer
@ -52,11 +52,11 @@ npm run smoke-test
Whenever you work on adding a feature/fixing a bug, this would probably be your first step. You create a test case and then run it through the generator, see the result, modify the generator, run it again and so on, until you get the desired output.
1. Pick up a cadl as your test input in cadl-ranch. Below are some examples
1. Pick up a typespec as your test input in cadl-ranch. Below are some examples
Let us say your test input is `authentication/api-key/main.cadl` in @azure-tools/cadl-ranch-specs.
Let us say your test input is `authentication/api-key/main.tsp` in @azure-tools/cadl-ranch-specs.
1. Now add an entry to the CadlRanchConfig to the file [`cadl-ranch-list.ts`](./test/commands/cadl-ranch-list.ts). In the file, add the following to the array.
1. Now add an entry to the TypeSpecRanchConfig to the file [`cadl-ranch-list.ts`](./test/commands/cadl-ranch-list.ts). In the file, add the following to the array.
```typescript
{
@ -78,7 +78,7 @@ Whenever you work on adding a feature/fixing a bug, this would probably be your
includeShortcuts: true
azureSdkForJs: false
addCredentials: false
isCadlTest: true
isTypeSpecTest: true
title: AuthApiKeyClient
packageDetails:
name: "@msinternal/auth-apikey"
@ -89,16 +89,16 @@ Whenever you work on adding a feature/fixing a bug, this would probably be your
1. Now, You can generate the RLC for your test case with the following command: (Initially, during your development, you do not want to run all the cases during every step of your development, you can comment out other test cases. But, once your code changes are complete for your case, then you need to run the entire suite to ensure that your changes did not cause any unwanted changes.)
```shell
npm run generate-cadl-only
npm run generate-tsp-only
```
1. Once you are satisfied with the generated code, you can add a spec file such as `testUserCaseRest.spec.ts` file [here](./test/integration). You can find several examples in the same place.
## How to debug
### `generate-cadl-only` step
### `generate-tsp-only` step
If you would like to debug the `generate-cadl-only` step for our test input, Open the repository in VS Code -> Select `Generate code for CadlEmitter` section -> Click `Attach`.
If you would like to debug the `generate-tsp-only` step for our test input, Open the repository in VS Code -> Select `Generate code for TypeSpec Emitter` section -> Click `Attach`.
### Spec file
@ -109,7 +109,7 @@ If you would like to debug the `testUserCase.spec.ts` file (after the SDK is gen
- In VS Code, We have created a Debugging profile for UnitTests to start debugging:
1. Go to the debugger tab
2. Select the "[CADL] - Unit Test" Profile
2. Select the "[TypeSpec] - Unit Test" Profile
3. Click the "Play" button
- Your breakpoints will start hitting, you can set breakpoints in either Test or Generator code
@ -123,15 +123,15 @@ If you would like to debug the `testUserCase.spec.ts` file (after the SDK is gen
- Once the Test Server is running
1. In VSCode go to the debugger tab
2. Select the "[CADL] - Integration Test" profile from the drop down
2. Select the "[TypeSpec] - Integration Test" profile from the drop down
3. Click the "Play" button
- **\*\***IMPORTANT**\*\***: Running Integration Tests for debugging, does not re-generate the test clients so make sure that after each change you do:
- Re-generate all the test swaggers
npm run generate-cadl-only -- --build
npm run generate-tsp-only -- --build
- Re-generate a specific swagger
npm run generate-cadl-only -- -i bodyComplexRest -b
npm run generate-tsp-only -- -i bodyComplexRest -b

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

@ -1,11 +1,11 @@
{
"name": "@azure-tools/typespec-ts",
"version": "0.15.0",
"description": "An experimental CADL emitter for TypeScript RLC",
"description": "An experimental TypeSpec emitter for TypeScript RLC",
"main": "dist/src/index.js",
"type": "module",
"scripts": {
"clean": "rimraf ./dist ./cadl-output",
"clean": "rimraf ./dist ./typespec-output",
"build": "tsc -p .",
"test": "npm run unit-test && npm run integration-test-ci",
"lint": "eslint src --ext .ts --max-warnings=0",
@ -21,16 +21,16 @@
"start-test-server:rlc": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript-rlc.json",
"start-test-server:modular": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript-modular.json",
"copy:typespec": "rm -rf temp && mkdirp -p temp && cp -r ./node_modules/@azure-tools/cadl-ranch-specs/http ./temp && cp -r ./test/integration/typespec/* ./temp/http",
"generate-and-run:rlc": "npm run generate-cadl-only:rlc && npm run integration-test:alone:rlc && npm run stop-test-server",
"generate-and-run:modular": "npm run generate-cadl-only:modular && npm run integration-test:alone:modular && npm run stop-test-server",
"generate-cadl-only": "npm run generate-cadl-only:rlc && npm run generate-cadl-only:modular",
"generate-cadl-only:rlc": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=rlc",
"generate-cadl-only:modular": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=modular",
"generate-and-run:rlc": "npm run generate-tsp-only:rlc && npm run integration-test:alone:rlc && npm run stop-test-server",
"generate-and-run:modular": "npm run generate-tsp-only:modular && npm run integration-test:alone:modular && npm run stop-test-server",
"generate-tsp-only": "npm run generate-tsp-only:rlc && npm run generate-tsp-only:modular",
"generate-tsp-only:rlc": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=rlc",
"generate-tsp-only:modular": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=modular",
"integration-test:alone": "npm run integration-test:alone:rlc && npm run integration-test:alone:modular",
"integration-test:alone:rlc": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/integration/*.spec.ts",
"integration-test:alone:modular": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/modularIntegration/*.spec.ts",
"stop-test-server": "npx cadl-ranch server stop",
"unit-test": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --timeout 4000 './test/unit/**/*.spec.ts'"
"unit-test": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --timeout 4000 './test/unit/**/*.spec.ts' './test/modularUnit/**/*.spec.ts'"
},
"author": "Jose Heredia <joheredi@microsoft.com>",
"license": "MIT",

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

@ -28,8 +28,6 @@ import {
buildSerializeHelper,
buildLogger,
RLCOptions,
normalizeName,
NameType,
hasUnexpectedHelper,
RLCModel
} from "@azure-tools/rlc-common";
@ -144,9 +142,15 @@ export async function $onEmit(context: EmitContext) {
const modularSourcesRoot =
dpgContext.generationPathDetail?.modularSourcesDir ?? "src";
const project = new Project();
modularCodeModel = emitCodeModel(context, serviceNameToRlcModelsMap, {
casing: "camel"
});
modularCodeModel = emitCodeModel(
dpgContext,
serviceNameToRlcModelsMap,
modularSourcesRoot,
project,
{
casing: "camel"
}
);
const rootIndexFile = project.createSourceFile(
`${modularSourcesRoot}/index.ts`,
"",
@ -155,59 +159,26 @@ export async function $onEmit(context: EmitContext) {
}
);
for (const subClient of modularCodeModel.clients) {
let subfolder = "";
if (modularCodeModel.clients.length > 1) {
subfolder = normalizeName(
subClient.name.replace("Client", ""),
NameType.File
);
}
buildModels(modularCodeModel, project, modularSourcesRoot, subfolder);
buildModelsOptions(subClient, project, modularSourcesRoot, subfolder);
buildModels(modularCodeModel, subClient);
buildModelsOptions(modularCodeModel, subClient);
const hasClientUnexpectedHelper =
needUnexpectedHelper.get(
subClient.rlcClientName.replace("Context", "Client")
) ?? false;
buildOperationFiles(
dpgContext,
modularCodeModel,
subClient,
project,
modularSourcesRoot,
subfolder,
hasClientUnexpectedHelper
);
buildClientContext(
dpgContext,
subClient,
project,
modularSourcesRoot,
subfolder
);
buildSubpathIndexFile(project, modularSourcesRoot, "models", subfolder);
buildSubpathIndexFile(project, modularSourcesRoot, "api", subfolder);
buildClassicalClient(
dpgContext,
subClient,
project,
modularSourcesRoot,
subfolder
);
buildClientContext(dpgContext, modularCodeModel, subClient);
buildSubpathIndexFile(modularCodeModel, subClient, "models");
buildSubpathIndexFile(modularCodeModel, subClient, "api");
buildClassicalClient(dpgContext, modularCodeModel, subClient);
if (modularCodeModel.clients.length > 1) {
buildSubClientIndexFile(
subClient,
project,
modularSourcesRoot,
subfolder
);
buildSubClientIndexFile(modularCodeModel, subClient);
}
buildRootIndex(
subClient,
project,
rootIndexFile,
modularSourcesRoot,
subfolder
);
buildRootIndex(modularCodeModel, subClient, rootIndexFile);
}
removeUnusedInterfaces(project);

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

@ -3,7 +3,7 @@
import {
paramMessage,
createCadlLibrary,
createTypeSpecLibrary,
JSONSchemaType
} from "@typespec/compiler";
import { RLCOptions } from "@azure-tools/rlc-common";
@ -49,7 +49,7 @@ export const RLCOptionsSchema: JSONSchemaType<RLCOptions> = {
generateSample: { type: "boolean", nullable: true },
azureSdkForJs: { type: "boolean", nullable: true },
azureOutputDirectory: { type: "string", nullable: true },
isCadlTest: { type: "boolean", nullable: true },
isTypeSpecTest: { type: "boolean", nullable: true },
title: { type: "string", nullable: true },
dependencyInfo: {
type: "object",
@ -189,7 +189,7 @@ const libDef = {
}
} as const;
export const $lib = createCadlLibrary(libDef);
export const $lib = createTypeSpecLibrary(libDef);
export const { reportDiagnostic } = $lib;
export const prettierTypeScriptOptions: Options = {

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

@ -3,7 +3,6 @@ import {
FunctionDeclarationStructure,
MethodDeclarationStructure,
OptionalKind,
Project,
Scope,
SourceFile,
StructureKind
@ -12,24 +11,24 @@ import { toCamelCase } from "../utils/casingUtils.js";
import { getClientParameters } from "./helpers/clientHelpers.js";
import { getClientName } from "./helpers/namingHelpers.js";
import { getOperationFunction } from "./helpers/operationHelpers.js";
import { Client } from "./modularCodeModel.js";
import { Client, ModularCodeModel } from "./modularCodeModel.js";
import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
import { getDocsFromDescription } from "./helpers/docsHelpers.js";
import { SdkContext } from "../utils/interfaces.js";
export function buildClassicalClient(
dpgContext: SdkContext,
client: Client,
project: Project,
srcPath: string,
subfolder: string
codeModel: ModularCodeModel,
client: Client
) {
const { description } = client;
const modularClientName = getClientName(client);
const classicalClientname = `${getClientName(client)}Client`;
const params = getClientParameters(client);
const srcPath = codeModel.modularOptions.sourceRoot;
const subfolder = client.subfolder ?? "";
const clientFile = project.createSourceFile(
const clientFile = codeModel.project.createSourceFile(
`${srcPath}/${
subfolder !== "" ? subfolder + "/" : ""
}${classicalClientname}.ts`

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

@ -1,8 +1,8 @@
import { FunctionDeclaration, Project, SourceFile } from "ts-morph";
import { FunctionDeclaration, SourceFile } from "ts-morph";
import { getClientParameters } from "./helpers/clientHelpers.js";
import { importCredential } from "./helpers/credentialHelpers.js";
import { getClientName } from "./helpers/namingHelpers.js";
import { Client, Parameter } from "./modularCodeModel.js";
import { Client, ModularCodeModel, Parameter } from "./modularCodeModel.js";
import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
import { getDocsFromDescription } from "./helpers/docsHelpers.js";
import { importModels } from "./buildOperations.js";
@ -13,21 +13,20 @@ import { SdkContext } from "../utils/interfaces.js";
*/
export function buildClientContext(
dpgContext: SdkContext,
client: Client,
project: Project,
srcPath: string = "src",
subfolder: string = ""
codeModel: ModularCodeModel,
client: Client
): SourceFile {
const { description, parameters } = client;
const { description, parameters, subfolder } = client;
const name = getClientName(client);
const clientContextFile = project.createSourceFile(
const srcPath = codeModel.modularOptions.sourceRoot;
const clientContextFile = codeModel.project.createSourceFile(
`${srcPath}/${
subfolder && subfolder !== "" ? subfolder + "/" : ""
}/api/${name}Context.ts`
);
let factoryFunction;
importModels(srcPath, clientContextFile, project, subfolder);
importModels(srcPath, clientContextFile, codeModel.project, subfolder);
clientContextFile.addImportDeclaration({
moduleSpecifier: "@azure-rest/core-client",
namedImports: ["ClientOptions"]

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

@ -30,7 +30,6 @@ import {
getFormat,
getMinItems,
getMaxItems,
EmitContext,
listServices,
Union,
Type,
@ -65,7 +64,6 @@ import {
isApiVersion,
getDefaultApiVersion,
getClientNamespaceString,
createSdkContext,
getSdkUnion,
getAllModels,
SdkSimpleType,
@ -82,15 +80,20 @@ import {
Type as HrlcType,
Header
} from "./modularCodeModel.js";
import { transformRLCOptions } from "../transform/transfromRLCOptions.js";
import { getEnrichedDefaultApiVersion } from "../utils/modelUtils.js";
import { camelToSnakeCase, toCamelCase } from "../utils/casingUtils.js";
import { RLCModel, getClientName } from "@azure-tools/rlc-common";
import {
RLCModel,
getClientName,
NameType,
normalizeName
} from "@azure-tools/rlc-common";
import {
getOperationGroupName,
getOperationName
} from "../utils/operationUtil.js";
import { SdkContext } from "../utils/interfaces.js";
import { Project } from "ts-morph";
interface HttpServerParameter {
type: "endpointPath";
@ -187,7 +190,7 @@ function handleDiscriminator(context: SdkContext, type: Model, model: any) {
}
}
}
// it is not included in properties of cadl but needed by python codegen
// it is not included in properties of typespec but needed by python codegen
if (discriminatorProperty) {
const discriminatorType = { ...discriminatorProperty.type };
discriminatorType.value = null;
@ -769,7 +772,7 @@ function emitBasicOperation(
innerResponse
);
if (isErrorModel(context.program, response.type)) {
// * is valid status code in cadl but invalid for autorest.python
// * is valid status code in typespec but invalid for autorest.python
if (response.statusCode === "*") {
exceptions.push(emittedResponse);
}
@ -821,7 +824,7 @@ function emitBasicOperation(
}
function isReadOnly(program: Program, type: ModelProperty): boolean {
// https://microsoft.github.io/cadl/standard-library/rest/operations#automatic-visibility
// https://microsoft.github.io/typespec/standard-library/http/operations#automatic-visibility
// Only "read" should be readOnly
const visibility = getVisibility(program, type);
if (visibility) {
@ -1158,7 +1161,7 @@ function emitListOrDict(
return undefined;
}
function mapCadlType(context: SdkContext, type: Type): any {
function mapTypeSpecType(context: SdkContext, type: Type): any {
switch (type.kind) {
case "Number":
return constantType(type.value, intOrFloat(type.value));
@ -1259,7 +1262,7 @@ function emitType(context: SdkContext, type: EmitterType): Record<string, any> {
if (type.kind === "CredentialTypeUnion") {
return emitCredentialUnion(type);
}
const builtinType = mapCadlType(context, type);
const builtinType = mapTypeSpecType(context, type);
if (builtinType !== undefined) {
// add in description elements for types derived from primitive types (SecureString, etc.)
const doc = getDoc(context.program, type);
@ -1528,7 +1531,8 @@ function emitClients(
operationGroups: emitOperationGroups(context, client, rlcModels),
url: server ? server.url : "",
apiVersions: [],
rlcClientName: rlcModels ? getClientName(rlcModels) : client.name
rlcClientName: rlcModels ? getClientName(rlcModels) : client.name,
subfolder: ""
};
const emittedApiVersionParam = getApiVersionParameter(context);
if (emittedApiVersionParam) {
@ -1561,21 +1565,24 @@ function getNamespaces(context: SdkContext): Set<string> {
}
export function emitCodeModel(
context: EmitContext<EmitterOptions>,
dpgContext: SdkContext,
rlcModelsMap: Map<string, RLCModel>,
modularSourcesRoot: string,
project: Project,
options: { casing: "snake" | "camel" } = { casing: "snake" }
): ModularCodeModel {
CASING = options.casing ?? CASING;
const dpgContext = createSdkContext(context);
const clientNamespaceString =
getClientNamespaceString(dpgContext)?.toLowerCase();
// Get types
const codeModel: ModularCodeModel = {
options: transformRLCOptions(context.options as any, dpgContext),
options: dpgContext.rlcOptions ?? {},
modularOptions: { sourceRoot: modularSourcesRoot },
namespace: clientNamespaceString,
subnamespaceToClients: {},
clients: [],
types: []
types: [],
project
};
const allModels = getAllModels(dpgContext);
@ -1586,12 +1593,25 @@ export function emitCodeModel(
for (const namespace of getNamespaces(dpgContext)) {
if (namespace === clientNamespaceString) {
codeModel.clients = emitClients(dpgContext, namespace, rlcModelsMap);
codeModel.clients.length > 1 &&
codeModel.clients.map((client) => {
client["subfolder"] = normalizeName(
client.name.replace("Client", ""),
NameType.File
);
});
} else {
codeModel["subnamespaceToClients"][namespace] = emitClients(
dpgContext,
namespace,
rlcModelsMap
);
codeModel["subnamespaceToClients"][namespace].length > 1 &&
(codeModel["subnamespaceToClients"][namespace] as HrlcClient[]).map(
(client) => {
client["subfolder"] = normalizeName(client.name, NameType.File);
}
);
}
}

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

@ -7,7 +7,7 @@ import {
getDeserializePrivateFunction,
getOperationOptionsName
} from "./helpers/operationHelpers.js";
import { Client, Operation } from "./modularCodeModel.js";
import { Client, ModularCodeModel, Operation } from "./modularCodeModel.js";
import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
import { getDocsFromDescription } from "./helpers/docsHelpers.js";
import { SdkContext } from "../utils/interfaces.js";
@ -19,10 +19,8 @@ import { SdkContext } from "../utils/interfaces.js";
*/
export function buildOperationFiles(
dpgContext: SdkContext,
codeModel: ModularCodeModel,
client: Client,
project: Project,
srcPath: string = "src",
subfolder: string = "",
needUnexpectedHelper: boolean = true
) {
for (const operationGroup of client.operationGroups) {
@ -33,7 +31,9 @@ export function buildOperationFiles(
// into a nameless operation group. We'll call this operations.
"operations";
const operationGroupFile = project.createSourceFile(
const subfolder = client.subfolder;
const srcPath = codeModel.modularOptions.sourceRoot;
const operationGroupFile = codeModel.project.createSourceFile(
`${srcPath}/${
subfolder && subfolder !== "" ? subfolder + "/" : ""
}api/${fileName}.ts`
@ -41,7 +41,7 @@ export function buildOperationFiles(
// Import models used from ./models.ts
// We SHOULD keep this because otherwise ts-morph will "helpfully" try to import models from the rest layer when we call fixMissingImports().
importModels(srcPath, operationGroupFile, project, subfolder);
importModels(srcPath, operationGroupFile, codeModel.project, subfolder);
const namedImports: string[] = [];
let clientType = "Client";

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

@ -1,14 +1,15 @@
import { Project, SourceFile } from "ts-morph";
import { getClientName } from "./helpers/namingHelpers.js";
import { Client } from "./modularCodeModel.js";
import { Client, ModularCodeModel } from "./modularCodeModel.js";
export function buildRootIndex(
codeModel: ModularCodeModel,
client: Client,
project: Project,
rootIndexFile: SourceFile,
srcPath: string,
subfolder: string
rootIndexFile: SourceFile
) {
const { project } = codeModel;
const srcPath = codeModel.modularOptions.sourceRoot;
const subfolder = client.subfolder ?? "";
const clientName = `${getClientName(client)}Client`;
const clientFile = project.getSourceFile(
`${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}${clientName}.ts`
@ -71,12 +72,12 @@ function exportModels(
}
export function buildSubClientIndexFile(
client: Client,
project: Project,
srcPath: string,
subfolder: string
codeModel: ModularCodeModel,
client: Client
) {
const subClientIndexFile = project.createSourceFile(
const subfolder = client.subfolder ?? "";
const srcPath = codeModel.modularOptions.sourceRoot;
const subClientIndexFile = codeModel.project.createSourceFile(
`${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}index.ts`,
undefined,
{ overwrite: true }
@ -85,12 +86,18 @@ export function buildSubClientIndexFile(
const clientFilePath = `${srcPath}/${
subfolder !== "" ? subfolder + "/" : ""
}${clientName}.ts`;
const clientFile = project.getSourceFile(clientFilePath);
const clientFile = codeModel.project.getSourceFile(clientFilePath);
if (!clientFile) {
throw new Error(`Couldn't find client file: ${clientFilePath}`);
}
exportClassicalClient(client, subClientIndexFile, subfolder, true);
exportModels(subClientIndexFile, project, srcPath, clientName, subfolder);
exportModels(
subClientIndexFile,
codeModel.project,
srcPath,
clientName,
subfolder
);
}

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

@ -1,20 +1,22 @@
import { join } from "path";
import { Project } from "ts-morph";
import { Client, ModularCodeModel } from "./modularCodeModel.js";
export function buildSubpathIndexFile(
project: Project,
srcPath: string,
subpath: string,
subfolder: string
codeModel: ModularCodeModel,
client: Client,
subpath: string
) {
const apiFilePattern = join(srcPath, subfolder, subpath);
const apiFiles = project.getSourceFiles().filter((file) => {
const { subfolder } = client;
const srcPath = codeModel.modularOptions.sourceRoot;
const apiFilePattern = join(srcPath, client.subfolder ?? "", subpath);
const apiFiles = codeModel.project.getSourceFiles().filter((file) => {
return file
.getFilePath()
.replace(/\\/g, "/")
.startsWith(apiFilePattern.replace(/\\/g, "/"));
});
const indexFile = project.createSourceFile(
const indexFile = codeModel.project.createSourceFile(
`${srcPath}/${subfolder}/${subpath}/index.ts`
);
for (const file of apiFiles) {

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

@ -1,4 +1,4 @@
import { Project, SourceFile } from "ts-morph";
import { SourceFile } from "ts-morph";
import { getType } from "./helpers/typeHelpers.js";
import { Client, ModularCodeModel, Type } from "./modularCodeModel.js";
import * as path from "path";
@ -10,9 +10,7 @@ import { buildOperationOptions } from "./buildOperations.js";
*/
export function buildModels(
codeModel: ModularCodeModel,
project: Project,
srcPath: string = "src",
subfolder: string = ""
subClient: Client
): SourceFile | undefined {
// We are generating both models and enums here
const coreClientTypes = new Set<string>();
@ -24,8 +22,9 @@ export function buildModels(
if (models.length === 0) {
return;
}
const modelsFile = project.createSourceFile(
path.join(`${srcPath}/`, subfolder, `models/models.ts`)
const srcPath = codeModel.modularOptions.sourceRoot;
const modelsFile = codeModel.project.createSourceFile(
path.join(`${srcPath}/`, subClient.subfolder ?? "", `models/models.ts`)
);
for (const model of codeModel.types) {
@ -71,10 +70,11 @@ export function buildModels(
if (!model.name) {
throw new Error("Can't generate a model that has no name");
}
modelsFile.addInterface({
const modelInterface = {
name: model.name,
isExported: true,
docs: getDocsFromDescription(model.description),
extends: [] as string[],
properties: properties.map((p) => {
const propertyMetadata = getType(p.type);
let propertyTypeName = propertyMetadata.name;
@ -94,7 +94,13 @@ export function buildModels(
type: propertyTypeName
};
})
});
};
model.type === "model"
? model.parents?.forEach((p) =>
modelInterface.extends.push(getType(p).name)
)
: undefined;
modelsFile.addInterface(modelInterface);
}
}
@ -125,13 +131,11 @@ function isAzureCoreError(t: Type) {
}
export function buildModelsOptions(
client: Client,
project: Project,
srcPath: string = "src",
subfolder: string = ""
codeModel: ModularCodeModel,
client: Client
) {
const modelOptionsFile = project.createSourceFile(
`${srcPath}/${subfolder}/models/options.ts`,
const modelOptionsFile = codeModel.project.createSourceFile(
`${codeModel.modularOptions.sourceRoot}/${client.subfolder}/models/options.ts`,
undefined,
{
overwrite: true

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

@ -1,11 +1,17 @@
import { OperationResponse, RLCOptions } from "@azure-tools/rlc-common";
import { Project } from "ts-morph";
export interface ModularOptions {
sourceRoot: string;
}
export interface ModularCodeModel {
options: RLCOptions;
modularOptions: ModularOptions;
namespace?: string;
subnamespaceToClients?: any;
clients: Client[];
types: Type[];
project: Project;
}
export interface Header {
@ -81,6 +87,7 @@ export interface Type {
isFixed?: boolean;
valueType?: Type;
elementType?: Type;
parents?: Type[];
xmlMetadata?: XmlMetadata;
format?: string;
properties?: Property[];
@ -96,6 +103,7 @@ export interface Client {
url: string;
apiVersions: any[];
rlcClientName: string;
subfolder?: string;
}
export type ParameterLocation =

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

@ -283,7 +283,7 @@ function transformNormalBody(
if (hasBinaryContent) {
descriptions.push("Value may contain any sequence of octets");
}
const type = extractNameFromCadlType(
const type = extractNameFromTypeSpecType(
dpgContext,
bodyType,
importedModels,
@ -319,7 +319,11 @@ function transformMultiFormBody(
const isModelBody = bodyType.kind === "Model";
if (!isModelBody) {
const type = extractNameFromCadlType(dpgContext, bodyType, importedModels);
const type = extractNameFromTypeSpecType(
dpgContext,
bodyType,
importedModels
);
const description = extractDescriptionsFromBody(
dpgContext,
bodyType,
@ -361,7 +365,7 @@ function transformMultiFormBody(
SchemaContext.Exception
])}>`;
} else {
type = extractNameFromCadlType(
type = extractNameFromTypeSpecType(
dpgContext,
paramType.type,
importedModels
@ -392,13 +396,13 @@ function getBodyDetail(
return { hasBinaryContent, hasFormContent };
}
function extractNameFromCadlType(
function extractNameFromTypeSpecType(
dpgContext: SdkContext,
cadlType: Type,
type: Type,
importedModels: Set<string>,
headers?: ParameterMetadata[]
) {
const bodySchema = getSchemaForType(dpgContext, cadlType, [
const bodySchema = getSchemaForType(dpgContext, type, [
SchemaContext.Input,
SchemaContext.Exception
]) as Schema;

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

@ -78,8 +78,8 @@ export function transformSchemas(
}
}
}
program.stateMap(modelKey).forEach((context, cadlModel) => {
const model = getSchemaForType(dpgContext, cadlModel, context);
program.stateMap(modelKey).forEach((context, tspModel) => {
const model = getSchemaForType(dpgContext, tspModel, context);
if (model) {
model.usage = context;
}

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

@ -66,7 +66,7 @@ function extractRLCOptions(
azureSdkForJs,
serviceInfo,
azureOutputDirectory,
sourceFrom: "Cadl",
sourceFrom: "TypeSpec",
enableOperationGroup
};
}

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

@ -134,7 +134,7 @@ export function getSchemaForType(
const program = dpgContext.program;
const type = getEffectiveModelFromType(program, typeInput);
const builtinType = mapCadlTypeToTypeScript(dpgContext, type, usage);
const builtinType = mapTypeSpecTypeToTypeScript(dpgContext, type, usage);
if (builtinType !== undefined) {
// add in description elements for types derived from primitive types (SecureString, etc.)
const doc = getDoc(program, type);
@ -284,7 +284,7 @@ function getSchemaForUnionVariant(
return getSchemaForType(dpgContext, variant, usage);
}
// An openapi "string" can be defined in several different ways in Cadl
// An openapi "string" can be defined in several different ways in typespec
function isOasString(type: Type): boolean {
if (type.kind === "String") {
// A string literal
@ -402,7 +402,7 @@ function validateDiscriminator(
* A "schema property" here is a property that is emitted to OpenAPI schema.
*
* Headers, parameters, status codes are not schema properties even they are
* represented as properties in Cadl.
* represented as properties in typespec.
*/
function isSchemaProperty(program: Program, property: ModelProperty) {
const headerInfo = getHeaderFieldName(program, property);
@ -652,86 +652,86 @@ function getSchemaForModel(
}
return modelSchema;
}
// Map an Cadl type to an OA schema. Returns undefined when the resulting
// Map an typespec type to an OA schema. Returns undefined when the resulting
// OA schema is just a regular object schema.
function mapCadlTypeToTypeScript(
function mapTypeSpecTypeToTypeScript(
dpgContext: SdkContext,
cadlType: Type,
type: Type,
usage?: SchemaContext[]
): any {
switch (cadlType.kind) {
switch (type.kind) {
case "Number":
return { type: `${cadlType.value}` };
return { type: `${type.value}` };
case "String":
return { type: `"${cadlType.value}"` };
return { type: `"${type.value}"` };
case "Boolean":
return { type: `${cadlType.value}` };
return { type: `${type.value}` };
case "Model":
return mapCadlStdTypeToTypeScript(dpgContext, cadlType, usage);
return mapTypeSpecStdTypeToTypeScript(dpgContext, type, usage);
}
if (cadlType.kind === undefined) {
if (typeof cadlType === "string") {
return { type: `"${cadlType}"` };
} else if (typeof cadlType === "number" || typeof cadlType === "boolean") {
return { type: `${cadlType}` };
if (type.kind === undefined) {
if (typeof type === "string") {
return { type: `"${type}"` };
} else if (typeof type === "number" || typeof type === "boolean") {
return { type: `${type}` };
}
}
}
function applyIntrinsicDecorators(
program: Program,
cadlType: Scalar | ModelProperty,
type: Scalar | ModelProperty,
target: any
): any {
const newTarget = { ...target };
const docStr = getDoc(program, cadlType);
const isString = isStringType(program, getPropertyType(cadlType));
const isNumeric = isNumericType(program, getPropertyType(cadlType));
const docStr = getDoc(program, type);
const isString = isStringType(program, getPropertyType(type));
const isNumeric = isNumericType(program, getPropertyType(type));
if (isString && !target.documentation && docStr) {
newTarget.description = docStr;
}
const restApiName = getProjectedName(program, cadlType, "json");
const restApiName = getProjectedName(program, type, "json");
if (restApiName) {
newTarget.name = restApiName;
}
const summaryStr = getSummary(program, cadlType);
const summaryStr = getSummary(program, type);
if (isString && !target.summary && summaryStr) {
newTarget.summary = summaryStr;
}
const formatStr = getFormat(program, cadlType);
const formatStr = getFormat(program, type);
if (isString && !target.format && formatStr) {
newTarget.format = formatStr;
}
const pattern = getPattern(program, cadlType);
const pattern = getPattern(program, type);
if (isString && !target.pattern && pattern) {
newTarget.pattern = pattern;
}
const minLength = getMinLength(program, cadlType);
const minLength = getMinLength(program, type);
if (isString && !target.minLength && minLength !== undefined) {
newTarget.minLength = minLength;
}
const maxLength = getMaxLength(program, cadlType);
const maxLength = getMaxLength(program, type);
if (isString && !target.maxLength && maxLength !== undefined) {
newTarget.maxLength = maxLength;
}
const minValue = getMinValue(program, cadlType);
const minValue = getMinValue(program, type);
if (isNumeric && !target.minimum && minValue !== undefined) {
newTarget.minimum = minValue;
}
const maxValue = getMaxValue(program, cadlType);
const maxValue = getMaxValue(program, type);
if (isNumeric && !target.maximum && maxValue !== undefined) {
newTarget.maximum = maxValue;
}
if (isSecret(program, cadlType)) {
if (isSecret(program, type)) {
newTarget.format = "password";
newTarget["x-ms-secret"] = true;
}
@ -779,15 +779,15 @@ function enumMemberType(member: EnumMember) {
return "string";
}
/**
* Map Cadl intrinsic models to open api definitions
* Map TypeSpec intrinsic models to open api definitions
*/
function mapCadlStdTypeToTypeScript(
function mapTypeSpecStdTypeToTypeScript(
dpgContext: SdkContext,
cadlType: Model,
type: Model,
usage?: SchemaContext[]
): any | undefined {
const program = dpgContext.program;
const indexer = (cadlType as Model).indexer;
const indexer = (type as Model).indexer;
if (indexer !== undefined) {
if (!isNeverType(indexer.key)) {
const name = indexer.key.name;
@ -802,7 +802,7 @@ function mapCadlStdTypeToTypeScript(
schema = {
type: "dictionary",
additionalProperties: valueType,
description: getDoc(program, cadlType)
description: getDoc(program, type)
};
if (
!program.checker.isStdType(indexer.value) &&
@ -836,7 +836,7 @@ function mapCadlStdTypeToTypeScript(
schema = {
type: "array",
items: getSchemaForType(dpgContext, indexer.value!, usage, true),
description: getDoc(program, cadlType)
description: getDoc(program, type)
};
if (
!program.checker.isStdType(indexer.value) &&
@ -895,10 +895,10 @@ function isUnionType(type: Type) {
function getSchemaForStdScalar(
program: Program,
cadlType: Scalar,
type: Scalar,
relevantProperty?: ModelProperty
) {
if (!program.checker.isStdType(cadlType)) {
if (!program.checker.isStdType(type)) {
return undefined;
}
@ -909,81 +909,81 @@ function getSchemaForStdScalar(
*/
if (relevantProperty) {
const encodeData = getEncode(program, relevantProperty);
if (encodeData && isEncodeTypeEffective(cadlType, encodeData)) {
cadlType = encodeData.type;
if (encodeData && isEncodeTypeEffective(type, encodeData)) {
type = encodeData.type;
}
}
const name = cadlType.name;
const description = getSummary(program, cadlType);
const name = type.name;
const description = getSummary(program, type);
switch (name) {
case "bytes":
return { type: "string", format: "byte", description };
case "integer":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number"
});
case "int8":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "int8"
});
case "int16":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "int16"
});
case "int32":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "int32"
});
case "int64":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "int64"
});
case "safeint":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "int64"
});
case "uint8":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "uint8"
});
case "uint16":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "uint16"
});
case "uint32":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "uint32"
});
case "uint64":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "uint64"
});
case "float64":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "double"
});
case "float32":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "float"
});
case "float":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "number",
format: "float"
});
case "string":
return applyIntrinsicDecorators(program, cadlType, {
return applyIntrinsicDecorators(program, type, {
type: "string"
});
case "boolean":
@ -1092,11 +1092,11 @@ function getEnumStringDescription(type: any) {
export function getFormattedPropertyDoc(
program: Program,
cadlType: ModelProperty | Type,
type: ModelProperty | Type,
schemaType: any,
sperator: string = "\n\n"
) {
const propertyDoc = getDoc(program, cadlType);
const propertyDoc = getDoc(program, type);
const enhancedDocFromType = getEnumStringDescription(schemaType);
if (propertyDoc && enhancedDocFromType) {
return `${propertyDoc}${sperator}${enhancedDocFromType}`;

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

@ -44,7 +44,7 @@ async function check_tree() {
);
throw new Error(
"Git tree is dirty, regenerate all test cadl files and make sure that there are no un-intended changes"
"Git tree is dirty, regenerate all typespec files and make sure that there are no un-intended changes"
);
}
}

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

@ -4,7 +4,7 @@ import pkg from "chalk";
const { bold } = pkg;
const logError = (str: string) => console.error(bold.red(str));
// tag could be "rlc" | "modular"
async function generateCadls(tag: string = "rlc", isDebugging?: boolean) {
async function generateTypeSpecs(tag: string = "rlc", isDebugging?: boolean) {
let list = rlcTsps;
if (tag === "modular") {
list = modularTsps;
@ -21,7 +21,7 @@ async function main() {
const isDebugging = process.argv.indexOf("--debug") !== -1;
const tagOptions = process.argv.filter((s) => s.startsWith("--tag="));
const tag = tagOptions[0]?.split("=")[1];
await generateCadls(tag, isDebugging);
await generateTypeSpecs(tag, isDebugging);
}
main().catch((error) => {

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: ArrayItemTypesClient
enableOperationGroup: true
packageDetails:

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

@ -5,7 +5,7 @@ options:
"emitter-output-dir": "{project-root}"
azureSdkForJs: false
addCredentials: false
isCadlTest: true
isTypeSpecTest: true
title: AuthApiKeyClient
packageDetails:
name: "@msinternal/auth-apikey"

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

@ -5,7 +5,7 @@ options:
"emitter-output-dir": "{project-root}"
azureSdkForJs: false
addCredentials: false
isCadlTest: true
isTypeSpecTest: true
title: AuthHttpCustomClient
packageDetails:
name: "@msinternal/auth-httpcustom"

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

@ -7,7 +7,7 @@ options:
generateTest: true
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: AuthOauth2Client
packageDetails:
name: "@msinternal/auth-oauth2"

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

@ -7,7 +7,7 @@ options:
generateTest: true
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: AuthUnionClient
packageDetails:
name: "@msinternal/auth-union"

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

@ -6,7 +6,7 @@ options:
generateMetadata: true
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: AzureCoreTraitsClient
packageDetails:
name: "@msinternal/azurecoretraits"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: AzureCoreClient
packageDetails:
name: "@msinternal/azurecore"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/client-structure-default"
description: "Client Structure Default Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/client-structure-multiclient"
description: "Client Structure MultiClient Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/client-structure-renamed"
description: "Client Structure RenamedOperaiton Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/client-structure-twoopgroup"
description: "Client Structure TwoOperationGroup Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: DictClient
enableOperationGroup: true
packageDetails:

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
packageDetails:
name: "@msinternal/encode-datetime"

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

@ -6,7 +6,7 @@ options:
generateMetadata: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
packageDetails:
name: "@msinternal/encode-duration"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/extensible-enums"
description: "Extensible Enums Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/extensible-fixed"
description: "Fixed Enums Test Service"

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

@ -7,6 +7,6 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/client-request-id"

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

@ -7,6 +7,6 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/repeatable-header"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/hello-world"
description: "Hello World Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
title: InternalClient
packageDetails:

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/lro-core"
description: "LRO Core Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/lro-rpc"
description: "LRO RPC Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: MediaTypesClient
packageDetails:
name: "@msinternal/media-types"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/empty-model"
description: "Empty model Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/model-inheritance"
description: "Model Inheritance Test Service"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
packageDetails:
name: "@msinternal/nullable-property"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
packageDetails:
name: "@msinternal/optional-property"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
packageDetails:
name: "@msinternal/property-types"

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

@ -6,7 +6,7 @@ options:
generateMetadata: true
generateTest: false
addCredentials: false
isCadlTest: true
isTypeSpecTest: true
azureSdkForJs: false
packageDetails:
name: "@msinternal/usage"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/visibility"
description: "Visibility Test Service"

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

@ -6,6 +6,6 @@ options:
generateMetadata: false
generateTest: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/media-types"

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

@ -8,6 +8,6 @@ options:
addCredentials: false
azureSdkForJs: false
enableOperationGroup: true
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/collectionFormat"

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

@ -8,7 +8,7 @@ options:
addCredentials: false
azureSdkForJs: false
enableOperationGroup: true
isCadlTest: true
isTypeSpecTest: true
title: CollectionFormatClient
packageDetails:
name: "@msinternal/collectionFormat"

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

@ -8,6 +8,6 @@ options:
addCredentials: false
azureSdkForJs: false
enableOperationGroup: true
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/parameterSpread"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: ProjectionClient
enableOperationGroup: true
packageDetails:

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: ServiceDrivenOldClient
packageDetails:
name: "@msinternal/srv-driven-1"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: ServiceDrivenNewClient
packageDetails:
name: "@msinternal/srv-driven-2"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: MultipleParamInServerPathClient
packageDetails:
name: "@msinternal/multipleparam"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: SingleParamInServerPathClient
packageDetails:
name: "@msinternal/singleparam"

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

@ -6,6 +6,6 @@ options:
generateMetadata: false
generateTest: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
packageDetails:
name: "@msinternal/media-types"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
enableOperationGroup: true
title: SpecialWordsClient
packageDetails:

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

@ -6,7 +6,7 @@ options:
generateTest: true
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: UnionBodyClient
packageDetails:
name: "@msinternal/union-body"

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

@ -6,7 +6,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
title: UnionsClient
packageDetails:
name: "@msinternal/unions"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/azure-core-basic"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/client-structure-default"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/client-structure-multiclient"

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

@ -6,7 +6,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/client-structure-renamed"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/client-structure-twoopgroup"

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

@ -7,7 +7,7 @@ options:
generateTest: false
addCredentials: false
azureSdkForJs: false
isCadlTest: true
isTypeSpecTest: true
isModularLibrary: true
packageDetails:
name: "@msinternal/azure-collection-format"

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

@ -0,0 +1,53 @@
import { assert } from "chai";
import { emitModularModelsFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("modular model type", () => {
it("shouldn't generate models if there is no operations", async () => {
const schemaOutput = await emitModularModelsFromTypeSpec(`
model Test {
prop: string;
}
`);
assert.ok(!schemaOutput);
});
});
describe("inheritance & polymorphism", () => {
it("should handle inheritance model", async () => {
const modelFile = await emitModularModelsFromTypeSpec(`
model Pet {
name: string;
weight?: float32;
}
model Cat extends Pet {
kind: "cat";
meow: int32;
}
model Dog extends Pet {
kind: "dog";
bark: string;
}
op read(): { @body body: Pet };
`);
assert.ok(modelFile);
assertEqualContent(
modelFile?.getFullText()!,
`
export interface Pet {
name: string;
weight?: number;
}
export interface Cat extends Pet {
kind: "cat";
meow: number;
}
export interface Dog extends Pet {
kind: "dog";
bark: string;
}`
);
});
});

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

@ -1,6 +1,6 @@
import { assert } from "chai";
import { emitClientFactoryFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitClientFactoryFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
interface DefinitionOptions {
"@service"?: boolean;
@ -257,7 +257,7 @@ describe("api-version", () => {
"@service": true
});
const expectedRes = buildDefaultReturn(true);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -266,7 +266,7 @@ describe("api-version", () => {
"@versioned": true
});
const expectedRes = buildDefaultReturn(true);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -279,7 +279,7 @@ describe("api-version", () => {
crossVersion: true
});
const expectedRes = buildDefaultReturn(false);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -289,7 +289,7 @@ describe("api-version", () => {
"@versioned": false
});
const expectedRes = buildDefaultReturn(false);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -302,7 +302,7 @@ describe("api-version", () => {
"@service": true
});
const expectedRes = buildPathReturn_WithDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -311,7 +311,7 @@ describe("api-version", () => {
"@versioned": true
});
const expectedRes = buildPathReturn_WithDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -323,7 +323,7 @@ describe("api-version", () => {
"@versioned": false
});
const expectedRes = buildPathReturn_WithoutDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -336,7 +336,7 @@ describe("api-version", () => {
"@service": true
});
const expectedRes = buildPathReturn_WithDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -345,7 +345,7 @@ describe("api-version", () => {
"@versioned": true
});
const expectedRes = buildPathReturn_WithDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -357,7 +357,7 @@ describe("api-version", () => {
"@versioned": false
});
const expectedRes = buildPathReturn_WithoutDefault();
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -370,7 +370,7 @@ describe("api-version", () => {
"@service": true
});
const expectedRes = buildDefaultReturn(true);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -379,7 +379,7 @@ describe("api-version", () => {
"@versioned": true
});
const expectedRes = buildDefaultReturn(true);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});
@ -391,7 +391,7 @@ describe("api-version", () => {
"@versioned": false
});
const expectedRes = buildDefaultReturn(false);
const models = await emitClientFactoryFromCadl(def);
const models = await emitClientFactoryFromTypeSpec(def);
assert.ok(models);
assertEqualContent(models!.content, expectedRes);
});

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

@ -1,8 +1,8 @@
import { assert } from "chai";
import {
emitParameterFromCadl,
emitResponsesFromCadl
} from "./util/emitUtil.js";
emitParameterFromTypeSpec,
emitResponsesFromTypeSpec
} from "../util/emitUtil.js";
describe("typespec-azure-core: operation templates", () => {
it("ResourceCreateWithServiceProvidedName", async () => {
@ -64,8 +64,8 @@ async function compileResourceOperation(code: string) {
#suppress "@azure-tools/typespec-azure-core/documentation-required" "for test"
${code}
`;
const parameters = await emitParameterFromCadl(content, true);
const responses = await emitResponsesFromCadl(content, true);
const parameters = await emitParameterFromTypeSpec(content, true);
const responses = await emitResponsesFromTypeSpec(content, true);
return { parameters, responses };
}

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

@ -1,10 +1,10 @@
import { assert } from "chai";
import { emitClientDefinitionFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitClientDefinitionFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("Client definition generation", () => {
it("should generate method-level parameter", async () => {
const clientDef = await emitClientDefinitionFromCadl(
const clientDef = await emitClientDefinitionFromTypeSpec(
`
@route("/{id}")
@doc("This is the longer description")
@ -38,7 +38,7 @@ describe("Client definition generation", () => {
});
it("should normalize method-level parameter", async () => {
const clientDef = await emitClientDefinitionFromCadl(
const clientDef = await emitClientDefinitionFromTypeSpec(
`
@route("/{TransactionID}")
@doc("This is the longer description")

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

@ -1,12 +1,12 @@
import { assert } from "chai";
import { emitClientFactoryFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitClientFactoryFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
import { Diagnostic } from "@typespec/compiler";
describe("Client Factory generation", () => {
describe("should handle url parameters", () => {
it("should handle zero parameter", async () => {
const models = await emitClientFactoryFromCadl(`
const models = await emitClientFactoryFromTypeSpec(`
@server(
"localhost",
"Language Service"
@ -52,7 +52,7 @@ describe("Client Factory generation", () => {
);
});
it("should handle one parameter", async () => {
const models = await emitClientFactoryFromCadl(`
const models = await emitClientFactoryFromTypeSpec(`
@server(
"{Endpoint}/language",
"Language Service",
@ -108,7 +108,7 @@ describe("Client Factory generation", () => {
});
it("should handle two parameters", async () => {
const models = await emitClientFactoryFromCadl(
const models = await emitClientFactoryFromTypeSpec(
`
@server(
"{Endpoint}/language/{Version}",
@ -178,7 +178,7 @@ describe("Client Factory generation", () => {
);
});
it("should handle extensible enums in host parameters", async () => {
const models = await emitClientFactoryFromCadl(
const models = await emitClientFactoryFromTypeSpec(
`
@server(
"{Endpoint}/language/{Version}",
@ -248,7 +248,7 @@ describe("Client Factory generation", () => {
describe("should handle no @server definition", () => {
it("should set default endpoint parameter when no @server", async () => {
const models = await emitClientFactoryFromCadl(`
const models = await emitClientFactoryFromTypeSpec(`
@service( {title: "PetStoreClient"})
namespace PetStore;
`);
@ -295,7 +295,7 @@ describe("Client Factory generation", () => {
describe("should handle different auth options", () => {
it("should not generate credential if scope is empty", async () => {
try {
await emitClientFactoryFromCadl(
await emitClientFactoryFromTypeSpec(
`
@useAuth(
OAuth2Auth<[{
@ -321,7 +321,7 @@ describe("Client Factory generation", () => {
});
it("should generate both credentials if both defined", async () => {
const models = await emitClientFactoryFromCadl(`
const models = await emitClientFactoryFromTypeSpec(`
@useAuth(
ApiKeyAuth<ApiKeyLocation.header, "apiKey"> |
OAuth2Auth<[{

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

@ -1,5 +1,5 @@
import { assert } from "chai";
import { getRLCClientsFromCadl } from "./util/emitUtil.js";
import { getRLCClientsFromTypeSpec } from "../util/emitUtil.js";
describe("client utils get rlc clients", () => {
it("should get the service client if no @client decorator", async () => {
@ -19,7 +19,7 @@ describe("client utils get rlc clients", () => {
op1(): void
}
`;
const clients = await getRLCClientsFromCadl(content);
const clients = await getRLCClientsFromTypeSpec(content);
assert.equal(clients.length, 1);
assert.equal(clients[0]?.name, "MyServiceClient");
});
@ -48,7 +48,7 @@ describe("client utils get rlc clients", () => {
interface MySecondInterface {
op2(): void
}`;
const clients = await getRLCClientsFromCadl(content);
const clients = await getRLCClientsFromTypeSpec(content);
assert.equal(clients.length, 1);
assert.equal(clients[0]?.name, "MyServiceClient");
});
@ -70,7 +70,7 @@ describe("client utils get rlc clients", () => {
op1(): void
}
`;
const clients = await getRLCClientsFromCadl(content);
const clients = await getRLCClientsFromTypeSpec(content);
assert.equal(clients.length, 1);
assert.equal(clients[0]?.name, "MyServiceClient");
});
@ -103,7 +103,7 @@ describe("client utils get rlc clients", () => {
}
}
`;
const clients = await getRLCClientsFromCadl(content);
const clients = await getRLCClientsFromTypeSpec(content);
assert.equal(clients.length, 2);
assert.equal(clients[0]?.name, "MyServiceClient");
assert.equal(clients[1]?.name, "MySecondServiceClient");
@ -144,7 +144,7 @@ describe("client utils get rlc clients", () => {
}
}
`;
const clients = await getRLCClientsFromCadl(content);
const clients = await getRLCClientsFromTypeSpec(content);
assert.equal(clients.length, 2);
assert.equal(clients[0]?.name, "MyServiceClient");
assert.equal(clients[1]?.name, "MySecondServiceClient");

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

@ -1,15 +1,15 @@
import { assert } from "chai";
import {
emitClientDefinitionFromCadl,
emitModelsFromCadl,
emitParameterFromCadl
} from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
emitClientDefinitionFromTypeSpec,
emitModelsFromTypeSpec,
emitParameterFromTypeSpec
} from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("Doc generation testing", () => {
describe("docs in models.ts & outputModels.ts", () => {
it("should generate model-level and property-level docs in input model", async () => {
const models = await emitModelsFromCadl(`
const models = await emitModelsFromTypeSpec(`
@doc("A simple model with doc")
model SimpleModel {
@doc("A test property.")
@ -33,7 +33,7 @@ describe("Doc generation testing", () => {
describe("docs in parameters.ts", () => {
it("should generate body description", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model UserDetailsParameter {
@body
@ -59,7 +59,7 @@ describe("Doc generation testing", () => {
);
});
it("shouldn't generate type description as body property description", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@doc("Body type details")
model UserDetailsParameter {
@ -84,7 +84,7 @@ describe("Doc generation testing", () => {
);
});
it("should generate query description", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@doc("The filter query parameter.")
model FilterParameter {
@ -115,7 +115,7 @@ describe("Doc generation testing", () => {
);
});
it("should generate header description with custom name", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
op test(@doc("test header") @header("x-my-header") MyHeader: string): string;
`
@ -141,7 +141,7 @@ describe("Doc generation testing", () => {
);
});
it("should generate contentType description", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
#suppress "@typespec/http/content-type-ignored" "for test"
op test(@doc("content type") @header contentType: "application/octet-stream"): string;
@ -166,7 +166,7 @@ describe("Doc generation testing", () => {
describe("docs in clientDefinitions.ts", () => {
it("should generate operation description", async () => {
const clientDef = await emitClientDefinitionFromCadl(
const clientDef = await emitClientDefinitionFromTypeSpec(
`
@summary("This is a summary")
@doc("This is the longer description")

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,5 +1,5 @@
import { assert } from "chai";
import { emitPageHelperFromCadl } from "./util/emitUtil.js";
import { emitPageHelperFromTypeSpec } from "../util/emitUtil.js";
describe("Page helper", () => {
it("could handle customized nextLinkName and itemName", async () => {
@ -39,5 +39,5 @@ async function generatePagingHelper(code: string) {
${code}
`;
return await emitPageHelperFromCadl(content, true);
return await emitPageHelperFromTypeSpec(content, true);
}

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

@ -1,12 +1,12 @@
import { assert } from "chai";
import { emitParameterFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitParameterFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("Parameters.ts", () => {
describe("query parameters", () => {
describe("apiVersion in query", () => {
it("should't generate apiVersion if there's a client level apiVersion", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model ApiVersionParameter {
@query
@ -27,7 +27,7 @@ describe("Parameters.ts", () => {
});
it("should generate apiVersion if there's no client level apiVersion", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model ApiVersionParameter {
@query
@ -59,7 +59,7 @@ describe("Parameters.ts", () => {
});
describe("other parameters in query", () => {
it("should generate user-custom-query ", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model CustomParameter {
@query
@ -88,7 +88,7 @@ describe("Parameters.ts", () => {
});
it("should generate offsetDateTime as Date | string", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model QueryParameter {
@query
@ -120,7 +120,7 @@ describe("Parameters.ts", () => {
describe("header parameters", () => {
it("should generate offsetDateTime as string", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
model QueryParameter {
@header
@ -151,7 +151,7 @@ describe("Parameters.ts", () => {
describe("binary request", () => {
it("bytes request with application/json will be treated as string", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@post op read(@body body: bytes): {};
`
@ -171,7 +171,7 @@ describe("Parameters.ts", () => {
});
it("bytes request should respect @header contentType and use binary format when not json or text", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@post op read(@header contentType: "image/png", @body body: bytes): {};
`
@ -205,7 +205,7 @@ describe("Parameters.ts", () => {
// TODO: we need more discussions about current behavior
// issue tracked https://github.com/Azure/autorest.typescript/issues/1486
it("multiple contentTypes defined @header", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@post op read(@header contentType: "image/png" | "application/json", @body body: bytes): {};
`
@ -237,7 +237,7 @@ describe("Parameters.ts", () => {
});
it("contentTypes has binary data", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@route("/uploadFileViaBody")
@post op uploadFileViaBody(
@ -273,7 +273,7 @@ describe("Parameters.ts", () => {
});
it("contentTypes has multiple form data", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@route("/uploadFile")
@post op uploadFile(
@ -316,7 +316,7 @@ describe("Parameters.ts", () => {
});
it("contentTypes has array data defined in form body", async () => {
const parameters = await emitParameterFromCadl(
const parameters = await emitParameterFromTypeSpec(
`
@route("/uploadFiles")
@post op uploadFiles(
@ -357,7 +357,7 @@ describe("Parameters.ts", () => {
describe("array as request body", () => {
it("unknown array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: unknown[]): void;
`);
assert.ok(parameters);
@ -375,7 +375,7 @@ describe("Parameters.ts", () => {
);
});
it("string array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: string[]): void;
`);
assert.ok(parameters);
@ -394,7 +394,7 @@ describe("Parameters.ts", () => {
});
it("int32 array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: int32[]): void ;
`);
assert.ok(parameters);
@ -413,7 +413,7 @@ describe("Parameters.ts", () => {
});
it("int64 array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: int64[]): void ;
`);
assert.ok(parameters);
@ -432,7 +432,7 @@ describe("Parameters.ts", () => {
});
it("float32 array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: float32[]): void ;
`);
assert.ok(parameters);
@ -451,7 +451,7 @@ describe("Parameters.ts", () => {
});
it("boolean array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: boolean[]): void ;
`);
assert.ok(parameters);
@ -470,7 +470,7 @@ describe("Parameters.ts", () => {
});
it("bytes array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: bytes[]): void ;
`);
assert.ok(parameters);
@ -489,7 +489,7 @@ describe("Parameters.ts", () => {
});
it("plainDate array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: plainDate[]): void;
`);
assert.ok(parameters);
@ -508,7 +508,7 @@ describe("Parameters.ts", () => {
});
it("datetime array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: utcDateTime[]): void;
`);
assert.ok(parameters);
@ -527,7 +527,7 @@ describe("Parameters.ts", () => {
});
it("duration array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
@post op read(@body body: duration[]): void;
`);
assert.ok(parameters);
@ -546,7 +546,7 @@ describe("Parameters.ts", () => {
});
it("SimpleModel array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model SimpleModel {
prop1: string;
prop2: int32;
@ -570,7 +570,7 @@ describe("Parameters.ts", () => {
});
it("InnerModel array request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model InnerModel {
property: string;
children?: InnerModel[];
@ -596,7 +596,7 @@ describe("Parameters.ts", () => {
describe("dictionary as request body", () => {
it("Simple model dictionary request generation", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model SimpleModel {
prop1: string;
prop2: int32;

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

@ -1,11 +1,11 @@
import { assert } from "chai";
import { emitResponsesFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitResponsesFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("Responses.ts", () => {
describe("property name generation", () => {
it("should generate property name with custome name", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
model SimpleModel {}
@doc("Metadata for long running operation status monitor locations")
model LongRunningStatusLocation {
@ -36,7 +36,7 @@ describe("Responses.ts", () => {
});
it("should generate property name without custome name", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
model SimpleModel {}
@doc("Metadata for long running operation status monitor locations")
model LongRunningStatusLocation {
@ -69,7 +69,7 @@ describe("Responses.ts", () => {
describe("statusCode generation", () => {
it("should generate property name with custome name", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@doc("Error")
@error
model Error {
@ -105,7 +105,7 @@ describe("Responses.ts", () => {
describe("body generation", () => {
it("unknown array response generation", async () => {
const parameters = await emitResponsesFromCadl(`
const parameters = await emitResponsesFromTypeSpec(`
@post op read(): unknown[];
`);
assert.ok(parameters);
@ -124,7 +124,7 @@ describe("Responses.ts", () => {
});
it("Record<SimpleModel> response generation", async () => {
const parameters = await emitResponsesFromCadl(`
const parameters = await emitResponsesFromTypeSpec(`
model SimpleModel {
prop1: string;
prop2: int32;
@ -148,7 +148,7 @@ describe("Responses.ts", () => {
});
it("should generate Record<unknown> as body property", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
op read(): Record<unknown>;
`);
assert.ok(responses);
@ -166,7 +166,7 @@ describe("Responses.ts", () => {
);
});
it("@header contentType not json or text should set format to binary(finally unit8array)", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): {@header contentType: "image/png", @body body: bytes};
`);
assert.ok(responses);
@ -185,7 +185,7 @@ describe("Responses.ts", () => {
);
});
it("@header contentType text/plain should keep format to byte(finally string)", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): {@header contentType: "text/plain", @body body: bytes};
`);
assert.ok(responses);
@ -206,7 +206,7 @@ describe("Responses.ts", () => {
describe("headers generation", () => {
it("merges headers from multiple responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
model Key {
key: string;
}
@ -241,7 +241,7 @@ describe("Responses.ts", () => {
describe("Array generation", () => {
it("verify string array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): string[];
`);
assert.ok(responses);
@ -260,7 +260,7 @@ describe("Responses.ts", () => {
});
it("verify int32 array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): int32[];
`);
assert.ok(responses);
@ -279,7 +279,7 @@ describe("Responses.ts", () => {
});
it("verify int64 array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): int64[];
`);
assert.ok(responses);
@ -298,7 +298,7 @@ describe("Responses.ts", () => {
});
it("verify float32 array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): float32[];
`);
assert.ok(responses);
@ -317,7 +317,7 @@ describe("Responses.ts", () => {
});
it("verify boolean array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): boolean[];
`);
assert.ok(responses);
@ -336,7 +336,7 @@ describe("Responses.ts", () => {
});
it("verify bytes array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): bytes[];
`);
assert.ok(responses);
@ -355,7 +355,7 @@ describe("Responses.ts", () => {
});
it("verify plainDate array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): plainDate[];
`);
assert.ok(responses);
@ -374,7 +374,7 @@ describe("Responses.ts", () => {
});
it("verify datetime array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): utcDateTime[];
`);
assert.ok(responses);
@ -393,7 +393,7 @@ describe("Responses.ts", () => {
});
it("verify duration array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
@get op read(): duration[];
`);
assert.ok(responses);
@ -412,7 +412,7 @@ describe("Responses.ts", () => {
});
it("verify SimpleModel array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
model SimpleModel {
prop1: string;
prop2: int32;
@ -436,7 +436,7 @@ describe("Responses.ts", () => {
});
it("verify InnerModel array from responses", async () => {
const responses = await emitResponsesFromCadl(`
const responses = await emitResponsesFromTypeSpec(`
model InnerModel {
property: string;
children?: InnerModel[];

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

@ -1,11 +1,11 @@
import { assert } from "chai";
import { emitParameterFromCadl } from "./util/emitUtil.js";
import { assertEqualContent } from "./util/testUtil.js";
import { emitParameterFromTypeSpec } from "../util/emitUtil.js";
import { assertEqualContent } from "../util/testUtil.js";
describe("Spread(...) and alias", () => {
describe("Parameter generation", async () => {
it("should flatten query and body properties with spread top-level model", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model User {
name: string;
}
@ -42,7 +42,7 @@ describe("Spread(...) and alias", () => {
});
it("should NOT flatten model properties with no other parts defined and top-level spread", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model SimpleModel {
id: string;
prop: string;
@ -66,7 +66,7 @@ describe("Spread(...) and alias", () => {
});
it("should flatten query and body properties with alias group properties", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model User {
name: string;
}
@ -104,7 +104,7 @@ describe("Spread(...) and alias", () => {
});
it("should flatten properties with one property in alias group and without position decorator", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
alias SimpleModel = {
name: string;
value?: int32;
@ -127,7 +127,7 @@ describe("Spread(...) and alias", () => {
});
it("should flatten properties with more than one properties in alias group with no position decorator", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model User {
name: string;
}
@ -164,7 +164,7 @@ describe("Spread(...) and alias", () => {
});
it("should flatten properties without any spread", async () => {
const parameters = await emitParameterFromCadl(`
const parameters = await emitParameterFromTypeSpec(`
model User {
name: string;
}

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

@ -6,27 +6,34 @@ import {
buildResponseTypes,
buildSchemaTypes,
ImportKind,
RLCModel,
Schema
} from "@azure-tools/rlc-common";
import { createDpgContextTestHelper, rlcEmitterFor } from "./testUtil.js";
import { transformToParameterTypes } from "../../../src/transform/transformParameters.js";
import { transformSchemas } from "../../../src/transform/transformSchemas.js";
import { transformPaths } from "../../../src/transform/transformPaths.js";
import { transformUrlInfo } from "../../../src/transform/transform.js";
import { transformApiVersionInfo } from "../../../src/transform/transformApiVersionInfo.js";
import { transformToResponseTypes } from "../../../src/transform/transformResponses.js";
import { getCredentialInfo } from "../../../src/transform/transfromRLCOptions.js";
import { getRLCClients } from "../../../src/utils/clientUtils.js";
import { transformToParameterTypes } from "../../src/transform/transformParameters.js";
import { transformSchemas } from "../../src/transform/transformSchemas.js";
import { transformPaths } from "../../src/transform/transformPaths.js";
import {
transformRLCModel,
transformUrlInfo
} from "../../src/transform/transform.js";
import { transformApiVersionInfo } from "../../src/transform/transformApiVersionInfo.js";
import { transformToResponseTypes } from "../../src/transform/transformResponses.js";
import { getCredentialInfo } from "../../src/transform/transfromRLCOptions.js";
import { getRLCClients } from "../../src/utils/clientUtils.js";
import { expectDiagnosticEmpty } from "@typespec/compiler/testing";
import { transformHelperFunctionDetails } from "../../../src/transform/transformHelperFunctionDetails.js";
import { transformHelperFunctionDetails } from "../../src/transform/transformHelperFunctionDetails.js";
import { emitCodeModel } from "../../src/modular/buildCodeModel.js";
import { buildModels } from "../../src/modular/emitModels.js";
import { Project } from "ts-morph";
export async function emitPageHelperFromCadl(
cadlContent: string,
export async function emitPageHelperFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false,
needTCGC: boolean = false
) {
const context = await rlcEmitterFor(
cadlContent,
tspContent,
true,
needAzureCore,
false,
@ -49,13 +56,13 @@ export async function emitPageHelperFromCadl(
});
}
export async function emitModelsFromCadl(
cadlContent: string,
export async function emitModelsFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false,
needTCGC: boolean = false
) {
const context = await rlcEmitterFor(
cadlContent,
tspContent,
true,
needAzureCore,
false,
@ -77,14 +84,14 @@ export async function emitModelsFromCadl(
});
}
export async function emitParameterFromCadl(
cadlContent: string,
export async function emitParameterFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false,
ignoreClientApiVersion: boolean = false,
needTCGC: boolean = false
) {
const context = await rlcEmitterFor(
cadlContent,
tspContent,
true,
needAzureCore,
ignoreClientApiVersion,
@ -108,11 +115,11 @@ export async function emitParameterFromCadl(
});
}
export async function emitClientDefinitionFromCadl(
cadlContent: string,
export async function emitClientDefinitionFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false
) {
const context = await rlcEmitterFor(cadlContent, true, needAzureCore);
const context = await rlcEmitterFor(tspContent, true, needAzureCore);
const program = context.program;
const dpgContext = createDpgContextTestHelper(context.program);
const clients = getRLCClients(dpgContext);
@ -129,12 +136,12 @@ export async function emitClientDefinitionFromCadl(
});
}
export async function emitClientFactoryFromCadl(
cadlContent: string,
export async function emitClientFactoryFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false,
isEmptyDiagnostic = true
) {
const context = await rlcEmitterFor(cadlContent, false, needAzureCore);
const context = await rlcEmitterFor(tspContent, false, needAzureCore);
const program = context.program;
const dpgContext = createDpgContextTestHelper(context.program);
const urlInfo = transformUrlInfo(dpgContext);
@ -167,11 +174,11 @@ export async function emitClientFactoryFromCadl(
});
}
export async function emitResponsesFromCadl(
cadlContent: string,
export async function emitResponsesFromTypeSpec(
tspContent: string,
needAzureCore: boolean = false
) {
const context = await rlcEmitterFor(cadlContent, true, needAzureCore);
const context = await rlcEmitterFor(tspContent, true, needAzureCore);
const dpgContext = createDpgContextTestHelper(context.program);
const importSet = new Map<ImportKind, Set<string>>();
const clients = getRLCClients(dpgContext);
@ -190,9 +197,9 @@ export async function emitResponsesFromCadl(
});
}
export async function getRLCClientsFromCadl(cadlContent: string) {
export async function getRLCClientsFromTypeSpec(tspContent: string) {
const context = await rlcEmitterFor(
cadlContent,
tspContent,
true,
false,
false,
@ -204,3 +211,38 @@ export async function getRLCClientsFromCadl(cadlContent: string) {
expectDiagnosticEmpty(dpgContext.program.diagnostics);
return clients;
}
export async function emitModularModelsFromTypeSpec(tspContent: string) {
const context = await rlcEmitterFor(tspContent, true);
const dpgContext = createDpgContextTestHelper(context.program);
const serviceNameToRlcModelsMap: Map<string, RLCModel> = new Map<
string,
RLCModel
>();
const project = new Project();
const clients = getRLCClients(dpgContext);
if (clients && clients[0]) {
dpgContext.rlcOptions!.isModularLibrary = true;
const rlcModels = await transformRLCModel(clients[0], dpgContext);
serviceNameToRlcModelsMap.set(clients[0].service.name, rlcModels);
const modularCodeModel = emitCodeModel(
dpgContext,
serviceNameToRlcModelsMap,
"",
project,
{
casing: "camel"
}
);
if (
modularCodeModel &&
modularCodeModel.clients &&
modularCodeModel.clients.length > 0 &&
modularCodeModel.clients[0]
) {
return buildModels(modularCodeModel, modularCodeModel.clients[0]);
}
}
expectDiagnosticEmpty(dpgContext.program.diagnostics);
return undefined;
}

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

@ -6,10 +6,10 @@ import { HttpTestLibrary } from "@typespec/http/testing";
import { VersioningTestLibrary } from "@typespec/versioning/testing";
import { AzureCoreTestLibrary } from "@azure-tools/typespec-azure-core/testing";
import { SdkTestLibrary } from "@azure-tools/typespec-client-generator-core/testing";
import { SdkContext } from "@azure-tools/typespec-client-generator-core";
import { SdkContext } from "../../src/utils/interfaces.js";
import { assert } from "chai";
import { format } from "prettier";
import { prettierTypeScriptOptions } from "../../../src/lib.js";
import { prettierTypeScriptOptions } from "../../src/lib.js";
export async function createRLCEmitterTestHost() {
return createTestHost({
@ -78,7 +78,9 @@ export function createDpgContextTestHelper(program: Program): SdkContext {
return {
program: program,
generateProtocolMethods: resolvedOptions.generateProtocolMethods,
generateConvenienceMethods: resolvedOptions.generateConvenienceMethods
generateConvenienceMethods: resolvedOptions.generateConvenienceMethods,
rlcOptions: {},
generationPathDetail: {}
} as SdkContext;
}

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

@ -32,5 +32,5 @@
"esm": true
},
"include": ["src/**/*.ts"],
"exclude": ["dist", "node_modules", "cadl-output"]
"exclude": ["dist", "node_modules", "typespec-output"]
}