diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 9f17219283..4d4793d4eb 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -201,6 +201,7 @@ importers: '@types/node': ^18.0.0 '@typespec/compiler': '>=0.63.0 <1.0.0' '@typespec/http': '>=0.63.0 <1.0.0' + '@typespec/json-schema': '>=0.63.0 <1.0.0' '@typespec/openapi': '>=0.63.0 <1.0.0' '@typespec/openapi3': '>=0.63.0 <1.0.0' '@typespec/rest': '>=0.63.0 <1.0.0' @@ -217,6 +218,7 @@ importers: '@azure-tools/typespec-ts': link:../typespec-ts '@typespec/compiler': 0.63.0 '@typespec/http': 0.63.0_@typespec+compiler@0.63.0 + '@typespec/json-schema': 0.63.0_@typespec+compiler@0.63.0 '@typespec/openapi': 0.63.0_qz2z3dajrrgsjonwob7haqlhte '@typespec/openapi3': 0.63.0_sqdvtoykz5tnrrjz5ge5rvjoie '@typespec/rest': 0.63.0_qz2z3dajrrgsjonwob7haqlhte @@ -2484,6 +2486,16 @@ packages: dependencies: '@typespec/compiler': 0.63.0 + /@typespec/json-schema/0.63.0_@typespec+compiler@0.63.0: + resolution: {integrity: sha512-jGRXxUxdrwW/XzvaDqyt5mS/V1iBnrDaHUMRIkrFLCwzgll/NenquLI/nopihzLFXK78MfFYuHg4DEPYY5PdFw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@typespec/compiler': ~0.63.0 + dependencies: + '@typespec/compiler': 0.63.0 + yaml: 2.5.1 + dev: false + /@typespec/openapi/0.63.0_qz2z3dajrrgsjonwob7haqlhte: resolution: {integrity: sha512-/KzR60mj3P/LnNWd/QfH0KTN/If4+mjrsWNSB7/uab6c8Qu/lNsGlZDkmWq4EFiwBR7VmpdFz9FP7d/m3O+tGw==} engines: {node: '>=18.0.0'} diff --git a/packages/typespec-test/package.json b/packages/typespec-test/package.json index 0926a3e8d5..3d31af86dd 100644 --- a/packages/typespec-test/package.json +++ b/packages/typespec-test/package.json @@ -15,6 +15,7 @@ "@typespec/http": ">=0.63.0 <1.0.0", "@typespec/rest": ">=0.63.0 <1.0.0", "@typespec/versioning": ">=0.63.0 <1.0.0", + "@typespec/json-schema": ">=0.63.0 <1.0.0", "prettier": "^3.1.0" }, "devDependencies": { diff --git a/packages/typespec-test/test/todo_non_branded/generated/openapi/openapi.json b/packages/typespec-test/test/todo_non_branded/generated/openapi/openapi.json index e749bb9762..eac5b5010a 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/openapi/openapi.json +++ b/packages/typespec-test/test/todo_non_branded/generated/openapi/openapi.json @@ -6,40 +6,6 @@ }, "tags": [], "paths": { - "/forgot-password": { - "post": { - "operationId": "Users_forgotPassword", - "description": "Sends a reset token to the user's email address", - "parameters": [], - "responses": { - "200": { - "description": "The request has succeeded." - }, - "404": { - "description": "The server cannot find the requested resource." - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "email": { - "type": "string", - "description": "The user's email address" - } - }, - "required": [ - "email" - ] - } - } - } - } - } - }, "/items": { "get": { "operationId": "TodoItems_list", @@ -61,11 +27,31 @@ } } } + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } + } + } + }, + "5XX": { + "description": "Something is wrong with me.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard5XXResponse" + } + } + } } } }, "post": { - "operationId": "TodoItems_createJson_TodoItems_createForm", + "operationId": "TodoItems_create", "parameters": [], "responses": { "200": { @@ -87,6 +73,26 @@ } } } + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } + } + } + }, + "5XX": { + "description": "Something is wrong with me.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard5XXResponse" + } + } + } } }, "requestBody": { @@ -97,40 +103,12 @@ "type": "object", "properties": { "item": { - "$ref": "#/components/schemas/TodoItem" - }, - "attachments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoUrlAttachment" - } - } - }, - "required": [ - "item", - "attachments" - ] - } - }, - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "item": { - "$ref": "#/components/schemas/TodoItem" + "$ref": "#/components/schemas/TodoItemCreate" }, "attachments": { "type": "array", "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TodoUrlAttachment" - }, - { - "type": "string", - "format": "byte" - } - ] + "$ref": "#/components/schemas/TodoAttachment" } } }, @@ -153,7 +131,8 @@ "required": true, "schema": { "type": "integer", - "format": "int64" + "format": "int64", + "readOnly": true } } ], @@ -169,7 +148,14 @@ } }, "404": { - "description": "The server cannot find the requested resource." + "description": "The server cannot find the requested resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodoItems.NotFoundErrorResponse" + } + } + } } } }, @@ -182,7 +168,8 @@ "required": true, "schema": { "type": "integer", - "format": "int64" + "format": "int64", + "readOnly": true } } ], @@ -203,12 +190,7 @@ "content": { "application/merge-patch+json": { "schema": { - "type": "object", - "properties": { - "patch": { - "$ref": "#/components/schemas/TodoItems.TodoItemPatch" - } - } + "$ref": "#/components/schemas/TodoItems.TodoItemPatch" } } } @@ -223,16 +205,44 @@ "required": true, "schema": { "type": "integer", - "format": "int64" + "format": "int64", + "readOnly": true } } ], "responses": { - "200": { - "description": "The request has succeeded." + "204": { + "description": "There is no content to send for this request, but the headers may be useful." }, "404": { - "description": "The server cannot find the requested resource." + "description": "The server cannot find the requested resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodoItems.NotFoundErrorResponse" + } + } + } + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } + } + } + }, + "5XX": { + "description": "Something is wrong with me.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard5XXResponse" + } + } + } } } } @@ -247,7 +257,8 @@ "required": true, "schema": { "type": "integer", - "format": "int64" + "format": "int64", + "readOnly": true } } ], @@ -257,21 +268,56 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoAttachment" + "type": "object", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TodoAttachment" + } + } } } } } }, "404": { - "description": "The server cannot find the requested resource." + "description": "The server cannot find the requested resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodoItems.NotFoundErrorResponse" + } + } + } + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } + } + } + }, + "5XX": { + "description": "Something is wrong with me.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard5XXResponse" + } + } + } } } }, "post": { - "operationId": "Attachments_createUrlAttachment_Attachments_createFileAttachment", + "operationId": "Attachments_createAttachment", "parameters": [ { "name": "itemId", @@ -279,62 +325,44 @@ "required": true, "schema": { "type": "integer", - "format": "int64" + "format": "int64", + "readOnly": true } } ], "responses": { - "200": { - "description": "The request has succeeded." + "204": { + "description": "There is no content to send for this request, but the headers may be useful." }, "404": { - "description": "The server cannot find the requested resource." - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contents": { - "$ref": "#/components/schemas/TodoUrlAttachment" - } - }, - "required": [ - "contents" - ] + "description": "The server cannot find the requested resource.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodoItems.NotFoundErrorResponse" + } } - }, - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "contents": { - "type": "string", - "format": "binary" - } - }, - "required": [ - "contents" - ] + } + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } } } - } - } - } - }, - "/login": { - "post": { - "operationId": "Users_login", - "parameters": [], - "responses": { - "200": { - "description": "The request has succeeded." }, - "401": { - "description": "Access is unauthorized." + "5XX": { + "description": "Something is wrong with me.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard5XXResponse" + } + } + } } }, "requestBody": { @@ -342,63 +370,13 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "username": { - "type": "string", - "maxLength": 50, - "description": "The user's username" - }, - "password": { - "type": "string", - "description": "The user's password, provided when creating a user\nbut is otherwise not visible (and hashed by the backend)" - } - }, - "required": [ - "username", - "password" - ] + "$ref": "#/components/schemas/TodoAttachment" } } } } } }, - "/logout": { - "get": { - "operationId": "Users_logout", - "parameters": [], - "responses": { - "200": { - "description": "The request has succeeded." - } - } - } - }, - "/reset-password": { - "get": { - "operationId": "Users_resetPassword", - "parameters": [ - { - "name": "resetToken", - "in": "query", - "required": true, - "schema": { - "type": "string" - }, - "explode": false - } - ], - "responses": { - "200": { - "description": "The request has succeeded." - }, - "404": { - "description": "The server cannot find the requested resource." - } - } - } - }, "/users": { "post": { "operationId": "Users_create", @@ -433,63 +411,50 @@ } } } - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "user": { - "$ref": "#/components/schemas/User" - } - }, - "required": [ - "user" - ] + }, + "4XX": { + "description": "Something is wrong with you.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Standard4XXResponse" + } } } - } - } - } - }, - "/validate": { - "get": { - "operationId": "Users_validate", - "parameters": [ - { - "name": "token", - "in": "query", - "required": true, - "schema": { - "type": "string" - }, - "explode": false - } - ], - "responses": { - "200": { - "description": "The request has succeeded." }, - "422": { - "description": "The user is invalid (e.g. forgot to enter email address)", + "5XX": { + "description": "Something is wrong with me.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Users.InvalidUserResponse" + "$ref": "#/components/schemas/Standard5XXResponse" } } } } - } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "security": [ + {} + ] } } }, "security": [ { "BearerAuth": [] + }, + { + "ApiKeyAuth": [] } ], "components": { @@ -497,7 +462,7 @@ "TodoItems.PaginationControls.limit": { "name": "limit", "in": "query", - "required": true, + "required": false, "description": "The limit to the number of items", "schema": { "type": "integer", @@ -509,7 +474,7 @@ "TodoItems.PaginationControls.offset": { "name": "offset", "in": "query", - "required": true, + "required": false, "description": "The offset to start paginating at", "schema": { "type": "integer", @@ -520,7 +485,7 @@ } }, "schemas": { - "Error": { + "ApiError": { "type": "object", "required": [ "code", @@ -533,10 +498,29 @@ }, "message": { "type": "string", - "description": "A human readable message" + "description": "A human readable message", + "x-ms-primary-error-message": true } } }, + "Standard4XXResponse": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ApiError" + } + ], + "description": "Something is wrong with you." + }, + "Standard5XXResponse": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ApiError" + } + ], + "description": "Something is wrong with me." + }, "TodoAttachment": { "anyOf": [ { @@ -550,17 +534,11 @@ "TodoFileAttachment": { "type": "object", "required": [ - "todoItemId", "filename", "mediaType", - "url" + "contents" ], "properties": { - "todoItemId": { - "type": "integer", - "format": "int64", - "description": "The todo item this is attached to" - }, "filename": { "type": "string", "maxLength": 255, @@ -570,10 +548,10 @@ "type": "string", "description": "The media type of the attachment" }, - "url": { + "contents": { "type": "string", - "format": "uri", - "description": "The url where the attachment can be downloaded from" + "format": "byte", + "description": "The contents of the file" } } }, @@ -583,19 +561,16 @@ "id", "title", "createdBy", - "ownedBy", - "description", "status", "createdAt", - "updatedAt", - "completedAt", - "labels" + "updatedAt" ], "properties": { "id": { "type": "integer", "format": "int64", - "description": "The item's unique id" + "description": "The item's unique id", + "readOnly": true }, "title": { "type": "string", @@ -608,7 +583,7 @@ "description": "User that created the todo", "readOnly": true }, - "ownedBy": { + "assignedTo": { "type": "integer", "format": "int64", "description": "User that the todo is assigned to", @@ -646,10 +621,46 @@ "readOnly": true }, "labels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoLabel" - } + "$ref": "#/components/schemas/TodoLabels" + } + } + }, + "TodoItemCreate": { + "type": "object", + "required": [ + "title", + "status" + ], + "properties": { + "title": { + "type": "string", + "maxLength": 255, + "description": "The item's title" + }, + "assignedTo": { + "type": "integer", + "format": "int64", + "description": "User that the todo is assigned to", + "readOnly": true + }, + "description": { + "type": "string", + "description": "A longer description of the todo item in markdown format" + }, + "status": { + "type": "string", + "enum": [ + "NotStarted", + "InProgress", + "Completed" + ], + "description": "The status of the todo item" + }, + "labels": { + "$ref": "#/components/schemas/TodoLabels" + }, + "_dummy": { + "type": "string" } } }, @@ -657,10 +668,24 @@ "type": "object", "allOf": [ { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/ApiError" } ] }, + "TodoItems.NotFoundErrorResponse": { + "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "not-found" + ] + } + } + }, "TodoItems.TodoItemPatch": { "type": "object", "properties": { @@ -669,15 +694,17 @@ "maxLength": 255, "description": "The item's title" }, - "ownedBy": { + "assignedTo": { "type": "integer", "format": "int64", "description": "User that the todo is assigned to", - "readOnly": true + "readOnly": true, + "nullable": true }, "description": { "type": "string", - "description": "A longer description of the todo item in markdown format" + "description": "A longer description of the todo item in markdown format", + "nullable": true }, "status": { "type": "string", @@ -694,7 +721,8 @@ "type": "object", "required": [ "items", - "pagination" + "pageSize", + "totalSize" ], "properties": { "items": { @@ -704,52 +732,56 @@ }, "description": "The items in the page" }, - "pagination": { - "type": "object", - "properties": { - "pageSize": { - "type": "integer", - "format": "int32", - "description": "The number of items returned in this page" - }, - "totalSize": { - "type": "integer", - "format": "int32", - "description": "The total number of items" - }, - "limit": { - "type": "integer", - "format": "int32", - "description": "The limit to the number of items", - "default": 50 - }, - "offset": { - "type": "integer", - "format": "int32", - "description": "The offset to start paginating at", - "default": 0 - }, - "prevLink": { - "type": "string", - "format": "uri", - "description": "A link to the previous page, if it exists" - }, - "nextLink": { - "type": "string", - "format": "uri", - "description": "A link to the next page, if it exists" - } - }, - "required": [ - "pageSize", - "totalSize", - "limit", - "offset" - ] + "pageSize": { + "type": "integer", + "format": "int32", + "description": "The number of items returned in this page" + }, + "totalSize": { + "type": "integer", + "format": "int32", + "description": "The total number of items" + }, + "limit": { + "type": "integer", + "format": "int32", + "description": "The limit to the number of items", + "default": 50 + }, + "offset": { + "type": "integer", + "format": "int32", + "description": "The offset to start paginating at", + "default": 0 + }, + "prevLink": { + "type": "string", + "format": "uri", + "description": "A link to the previous page, if it exists" + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "A link to the next page, if it exists" } } }, - "TodoLabel": { + "TodoLabelRecord": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "color": { + "type": "string", + "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$" + } + } + }, + "TodoLabels": { "anyOf": [ { "type": "string" @@ -771,20 +803,6 @@ } ] }, - "TodoLabelRecord": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "color": { - "type": "string" - } - } - }, "TodoUrlAttachment": { "type": "object", "required": [ @@ -813,6 +831,7 @@ "properties": { "username": { "type": "string", + "minLength": 2, "maxLength": 50, "description": "The user's username" }, @@ -828,9 +847,20 @@ }, "Users.InvalidUserResponse": { "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "invalid-user" + ] + } + }, "allOf": [ { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/ApiError" } ], "description": "The user is invalid (e.g. forgot to enter email address)" @@ -852,6 +882,7 @@ }, "username": { "type": "string", + "minLength": 2, "maxLength": 50, "description": "The user's username" }, @@ -867,9 +898,20 @@ }, "Users.UserExistsResponse": { "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "user-exists" + ] + } + }, "allOf": [ { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/ApiError" } ], "description": "The user already exists" @@ -879,6 +921,11 @@ "BearerAuth": { "type": "http", "scheme": "bearer" + }, + "ApiKeyAuth": { + "type": "apiKey", + "in": "cookie", + "name": "session-id" } } } diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/README.md b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/README.md index 806c22047c..93044c2e75 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/README.md +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/README.md @@ -1,4 +1,4 @@ -# Todo REST client library for JavaScript +# Todo client library for JavaScript @@ -14,7 +14,7 @@ Key links: ### Install the `@notabrand/todo-non-branded` package -Install the Todo REST client library for JavaScript with `npm`: +Install the Todo client library for JavaScript with `npm`: ```bash npm install @notabrand/todo-non-branded diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/package.json b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/package.json index f673672761..5de973201a 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/package.json +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/package.json @@ -10,7 +10,12 @@ "tshy": { "exports": { "./package.json": "./package.json", - ".": "./src/index.ts" + ".": "./src/index.ts", + "./models": "./src/models/index.ts", + "./api": "./src/api/index.ts", + "./api/users": "./src/api/users/index.ts", + "./api/todoItems": "./src/api/todoItems/index.ts", + "./api/todoItems/attachments": "./src/api/todoItems/attachments/index.ts" }, "dialects": [ "esm", @@ -63,6 +68,96 @@ "types": "./dist/commonjs/index.d.ts", "default": "./dist/commonjs/index.js" } + }, + "./models": { + "browser": { + "types": "./dist/browser/models/index.d.ts", + "default": "./dist/browser/models/index.js" + }, + "react-native": { + "types": "./dist/react-native/models/index.d.ts", + "default": "./dist/react-native/models/index.js" + }, + "import": { + "types": "./dist/esm/models/index.d.ts", + "default": "./dist/esm/models/index.js" + }, + "require": { + "types": "./dist/commonjs/models/index.d.ts", + "default": "./dist/commonjs/models/index.js" + } + }, + "./api": { + "browser": { + "types": "./dist/browser/api/index.d.ts", + "default": "./dist/browser/api/index.js" + }, + "react-native": { + "types": "./dist/react-native/api/index.d.ts", + "default": "./dist/react-native/api/index.js" + }, + "import": { + "types": "./dist/esm/api/index.d.ts", + "default": "./dist/esm/api/index.js" + }, + "require": { + "types": "./dist/commonjs/api/index.d.ts", + "default": "./dist/commonjs/api/index.js" + } + }, + "./api/users": { + "browser": { + "types": "./dist/browser/api/users/index.d.ts", + "default": "./dist/browser/api/users/index.js" + }, + "react-native": { + "types": "./dist/react-native/api/users/index.d.ts", + "default": "./dist/react-native/api/users/index.js" + }, + "import": { + "types": "./dist/esm/api/users/index.d.ts", + "default": "./dist/esm/api/users/index.js" + }, + "require": { + "types": "./dist/commonjs/api/users/index.d.ts", + "default": "./dist/commonjs/api/users/index.js" + } + }, + "./api/todoItems": { + "browser": { + "types": "./dist/browser/api/todoItems/index.d.ts", + "default": "./dist/browser/api/todoItems/index.js" + }, + "react-native": { + "types": "./dist/react-native/api/todoItems/index.d.ts", + "default": "./dist/react-native/api/todoItems/index.js" + }, + "import": { + "types": "./dist/esm/api/todoItems/index.d.ts", + "default": "./dist/esm/api/todoItems/index.js" + }, + "require": { + "types": "./dist/commonjs/api/todoItems/index.d.ts", + "default": "./dist/commonjs/api/todoItems/index.js" + } + }, + "./api/todoItems/attachments": { + "browser": { + "types": "./dist/browser/api/todoItems/attachments/index.d.ts", + "default": "./dist/browser/api/todoItems/attachments/index.js" + }, + "react-native": { + "types": "./dist/react-native/api/todoItems/attachments/index.d.ts", + "default": "./dist/react-native/api/todoItems/attachments/index.js" + }, + "import": { + "types": "./dist/esm/api/todoItems/attachments/index.d.ts", + "default": "./dist/esm/api/todoItems/attachments/index.js" + }, + "require": { + "types": "./dist/commonjs/api/todoItems/attachments/index.d.ts", + "default": "./dist/commonjs/api/todoItems/attachments/index.js" + } } }, "main": "./dist/commonjs/index.js", diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/review/todo-non-branded.api.md b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/review/todo-non-branded.api.md index 732e2ce5ac..06adde345d 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/review/todo-non-branded.api.md +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/review/todo-non-branded.api.md @@ -4,366 +4,157 @@ ```ts -import { Client } from '@typespec/ts-http-runtime'; import { ClientOptions } from '@typespec/ts-http-runtime'; -import { HttpResponse } from '@typespec/ts-http-runtime'; import { KeyCredential } from '@typespec/ts-http-runtime'; -import { RequestParameters } from '@typespec/ts-http-runtime'; -import { StreamableMethod } from '@typespec/ts-http-runtime'; +import { OperationOptions } from '@typespec/ts-http-runtime'; +import { Pipeline } from '@typespec/ts-http-runtime'; // @public -function createClient(endpointParam: string, credentials: KeyCredential, options?: TodoClientOptions): TodoClient; -export default createClient; - -// @public (undocumented) -export interface ErrorModelOutput { - code: string; - message: string; -} - -// @public (undocumented) -export interface InvalidTodoItemOutput extends ErrorModelOutput { +export interface PageTodoAttachment { + // (undocumented) + items: TodoAttachment[]; } // @public -export interface InvalidUserResponseOutput extends ErrorModelOutput { -} +export type TodoAttachment = TodoFileAttachment | TodoUrlAttachment; // @public (undocumented) -export interface Routes { - (path: "/users"): UsersCreate; - (path: "/validate"): UsersValidate; - (path: "/login"): UsersLogin; - (path: "/logout"): UsersLogout; - (path: "/forgot-password"): UsersForgotPassword; - (path: "/reset-password"): UsersResetPassword; - (path: "/items"): TodoItemsList; - (path: "/items/{id}", id: number): TodoItemsGet; - (path: "/items/{itemId}/attachments", itemId: number): TodoItemsAttachmentsList; +export class TodoClient { + constructor(endpointParam: string, credential: KeyCredential, options?: TodoClientOptionalParams); + readonly pipeline: Pipeline; + readonly todoItems: TodoItemsOperations; + readonly users: UsersOperations; } // @public -export type TodoAttachmentOutput = TodoFileAttachmentOutput | TodoUrlAttachmentOutput; - -// @public (undocumented) -export type TodoClient = Client & { - path: Routes; -}; - -// @public -export interface TodoClientOptions extends ClientOptions { +export interface TodoClientOptionalParams extends ClientOptions { } -// @public (undocumented) -export interface TodoFileAttachmentOutput { +// @public +export interface TodoFileAttachment { + contents: Uint8Array; filename: string; mediaType: string; - todoItemId: number; - url: string; } -// @public (undocumented) +// @public export interface TodoItem { - description: string; - id: number; - // (undocumented) - labels: TodoLabel[]; - ownedBy: number; - status: "NotStarted" | "InProgress" | "Completed"; - title: string; -} - -// @public (undocumented) -export interface TodoItemOutput { - readonly completedAt: string; - readonly createdAt: string; + assignedTo?: number; + readonly completedAt?: Date; + readonly createdAt: Date; readonly createdBy: number; - description: string; - id: number; + description?: string; + // (undocumented) + dummy?: string; + readonly id: number; // (undocumented) - labels: TodoLabelOutput[]; - ownedBy: number; + labels?: TodoLabels; status: "NotStarted" | "InProgress" | "Completed"; title: string; - readonly updatedAt: string; + readonly updatedAt: Date; } -// @public (undocumented) +// @public export interface TodoItemPatch { - description?: string; - ownedBy?: number; + assignedTo?: number | null; + description?: string | null; status?: "NotStarted" | "InProgress" | "Completed"; title?: string; } // @public -export interface TodoItemsAttachmentsCreateFileAttachment200Response extends HttpResponse { - // (undocumented) - status: "200"; +export interface TodoItemsAttachmentsCreateAttachmentOptionalParams extends OperationOptions { } // @public -export interface TodoItemsAttachmentsCreateFileAttachment404Response extends HttpResponse { - // (undocumented) - status: "404"; +export interface TodoItemsAttachmentsListOptionalParams extends OperationOptions { } -// @public (undocumented) -export interface TodoItemsAttachmentsCreateFileAttachmentBodyParam { - // (undocumented) - body: FormData | Array<{ - name: "contents"; - body: string | Uint8Array | ReadableStream | NodeJS.ReadableStream | File; - filename?: string; - contentType?: string; - }>; -} - -// @public (undocumented) -export interface TodoItemsAttachmentsCreateFileAttachmentMediaTypesParam { - // (undocumented) - contentType: "multipart/form-data"; -} - -// @public (undocumented) -export type TodoItemsAttachmentsCreateFileAttachmentParameters = TodoItemsAttachmentsCreateFileAttachmentMediaTypesParam & TodoItemsAttachmentsCreateFileAttachmentBodyParam & RequestParameters; - // @public -export interface TodoItemsAttachmentsCreateUrlAttachment200Response extends HttpResponse { +export interface TodoItemsAttachmentsOperations { // (undocumented) - status: "200"; -} - -// @public -export interface TodoItemsAttachmentsCreateUrlAttachment404Response extends HttpResponse { + createAttachment: (itemId: number, contents: TodoAttachment, options?: TodoItemsAttachmentsCreateAttachmentOptionalParams) => Promise; // (undocumented) - status: "404"; -} - -// @public (undocumented) -export interface TodoItemsAttachmentsCreateUrlAttachmentBodyParam { - // (undocumented) - body: { - contents: TodoUrlAttachment; - }; -} - -// @public (undocumented) -export interface TodoItemsAttachmentsCreateUrlAttachmentMediaTypesParam { - // (undocumented) - contentType: "application/json"; -} - -// @public (undocumented) -export type TodoItemsAttachmentsCreateUrlAttachmentParameters = TodoItemsAttachmentsCreateUrlAttachmentMediaTypesParam & TodoItemsAttachmentsCreateUrlAttachmentBodyParam & RequestParameters; - -// @public (undocumented) -export interface TodoItemsAttachmentsList { - // (undocumented) - get(options?: TodoItemsAttachmentsListParameters): StreamableMethod; - // (undocumented) - post(options: TodoItemsAttachmentsCreateUrlAttachmentParameters): StreamableMethod; - // (undocumented) - post(options: TodoItemsAttachmentsCreateFileAttachmentParameters): StreamableMethod; + list: (itemId: number, options?: TodoItemsAttachmentsListOptionalParams) => Promise; } // @public -export interface TodoItemsAttachmentsList200Response extends HttpResponse { +export interface TodoItemsCreateOptionalParams extends OperationOptions { // (undocumented) - body: TodoAttachmentOutput[]; + attachments?: TodoAttachment[]; // (undocumented) - status: "200"; + contentType?: string; } // @public -export interface TodoItemsAttachmentsList404Response extends HttpResponse { - // (undocumented) - status: "404"; +export interface TodoItemsDeleteOptionalParams extends OperationOptions { } -// @public (undocumented) -export type TodoItemsAttachmentsListParameters = RequestParameters; - // @public -export interface TodoItemsCreateForm200Response extends HttpResponse { - // (undocumented) - body: TodoItemOutput; - // (undocumented) - status: "200"; +export interface TodoItemsGetOptionalParams extends OperationOptions { } // @public -export interface TodoItemsCreateForm422Response extends HttpResponse { - // (undocumented) - body: InvalidTodoItemOutput; - // (undocumented) - status: "422"; -} - -// @public (undocumented) -export interface TodoItemsCreateFormBodyParam { - // (undocumented) - body: FormData | Array<{ - name: "item"; - body: TodoItem; - } | { - name: "attachments"; - body: TodoUrlAttachment | string | Uint8Array | ReadableStream | NodeJS.ReadableStream | File; - filename?: string; - contentType?: string; - }>; -} - -// @public (undocumented) -export interface TodoItemsCreateFormMediaTypesParam { - // (undocumented) - contentType: "multipart/form-data"; -} - -// @public (undocumented) -export type TodoItemsCreateFormParameters = TodoItemsCreateFormMediaTypesParam & TodoItemsCreateFormBodyParam & RequestParameters; - -// @public -export interface TodoItemsCreateJson200Response extends HttpResponse { - // (undocumented) - body: TodoItemOutput; - // (undocumented) - status: "200"; -} - -// @public -export interface TodoItemsCreateJson422Response extends HttpResponse { - // (undocumented) - body: InvalidTodoItemOutput; - // (undocumented) - status: "422"; -} - -// @public (undocumented) -export interface TodoItemsCreateJsonBodyParam { - // (undocumented) - body: { - item: TodoItem; - attachments: Array; - }; -} - -// @public (undocumented) -export interface TodoItemsCreateJsonMediaTypesParam { - // (undocumented) - contentType: "application/json"; -} - -// @public (undocumented) -export type TodoItemsCreateJsonParameters = TodoItemsCreateJsonMediaTypesParam & TodoItemsCreateJsonBodyParam & RequestParameters; - -// @public -export interface TodoItemsDelete200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public -export interface TodoItemsDelete404Response extends HttpResponse { - // (undocumented) - status: "404"; -} - -// @public (undocumented) -export type TodoItemsDeleteParameters = RequestParameters; - -// @public (undocumented) -export interface TodoItemsGet { - // (undocumented) - delete(options?: TodoItemsDeleteParameters): StreamableMethod; - // (undocumented) - get(options?: TodoItemsGetParameters): StreamableMethod; - // (undocumented) - patch(options: TodoItemsUpdateParameters): StreamableMethod; +export interface TodoItemsListOptionalParams extends OperationOptions { + limit?: number; + offset?: number; } // @public -export interface TodoItemsGet200Response extends HttpResponse { - // (undocumented) - body: TodoItemOutput; +export interface TodoItemsOperations { // (undocumented) - status: "200"; -} - -// @public -export interface TodoItemsGet404Response extends HttpResponse { + attachments: TodoItemsAttachmentsOperations; // (undocumented) - status: "404"; -} - -// @public (undocumented) -export type TodoItemsGetParameters = RequestParameters; - -// @public (undocumented) -export interface TodoItemsList { - // (undocumented) - get(options: TodoItemsListParameters): StreamableMethod; - // (undocumented) - post(options: TodoItemsCreateJsonParameters): StreamableMethod; - // (undocumented) - post(options: TodoItemsCreateFormParameters): StreamableMethod; -} - -// @public -export interface TodoItemsList200Response extends HttpResponse { - // (undocumented) - body: TodoPageOutput; - // (undocumented) - status: "200"; -} - -// @public (undocumented) -export type TodoItemsListParameters = TodoItemsListQueryParam & RequestParameters; - -// @public (undocumented) -export interface TodoItemsListQueryParam { + create: (item: TodoItem, options?: TodoItemsCreateOptionalParams) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; + delete: (id: number, options?: TodoItemsDeleteOptionalParams) => Promise; + // (undocumented) + get: (id: number, options?: TodoItemsGetOptionalParams) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; // (undocumented) - queryParameters: TodoItemsListQueryParamProperties; -} - -// @public (undocumented) -export interface TodoItemsListQueryParamProperties { - limit: number; - offset: number; + list: (options?: TodoItemsListOptionalParams) => Promise; + // (undocumented) + update: (id: number, patch: TodoItemPatch, options?: TodoItemsUpdateOptionalParams) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; } // @public -export interface TodoItemsUpdate200Response extends HttpResponse { - // (undocumented) - body: TodoItemOutput; - // (undocumented) - status: "200"; -} - -// @public (undocumented) -export interface TodoItemsUpdateBodyParam { +export interface TodoItemsUpdateOptionalParams extends OperationOptions { // (undocumented) - body: { - patch: TodoItemPatch; - }; + contentType?: string; } -// @public (undocumented) -export interface TodoItemsUpdateMediaTypesParam { - // (undocumented) - contentType: "application/merge-patch+json"; -} - -// @public (undocumented) -export type TodoItemsUpdateParameters = TodoItemsUpdateMediaTypesParam & TodoItemsUpdateBodyParam & RequestParameters; - -// @public -export type TodoLabel = string | string[] | TodoLabelRecord | Array; - // @public -export type TodoLabelOutput = string | string[] | TodoLabelRecordOutput | Array; - -// @public (undocumented) export interface TodoLabelRecord { // (undocumented) color?: string; @@ -371,238 +162,45 @@ export interface TodoLabelRecord { name: string; } -// @public (undocumented) -export interface TodoLabelRecordOutput { - // (undocumented) - color?: string; - // (undocumented) - name: string; -} +// @public +export type TodoLabels = string | string[] | TodoLabelRecord | TodoLabelRecord[]; -// @public (undocumented) -export interface TodoPageOutput { - items: Array; - // (undocumented) - pagination: { - pageSize: number; - totalSize: number; - prevLink?: string; - nextLink?: string; - }; +// @public +export interface TodoPage { + items: TodoItem[]; + nextLink?: string; + pageSize: number; + prevLink?: string; + totalSize: number; } -// @public (undocumented) +// @public export interface TodoUrlAttachment { description: string; url: string; } -// @public (undocumented) -export interface TodoUrlAttachmentOutput { - description: string; - url: string; -} - -// @public (undocumented) +// @public export interface User { - email: string; - password: string; - username: string; -} - -// @public (undocumented) -export interface UserCreatedResponseOutput { email: string; readonly id: number; password: string; - token: string; username: string; } // @public -export interface UserExistsResponseOutput extends ErrorModelOutput { -} - -// @public (undocumented) -export interface UsersCreate { - // (undocumented) - post(options: UsersCreateParameters): StreamableMethod; -} - -// @public -export interface UsersCreate200Response extends HttpResponse { - // (undocumented) - body: UserCreatedResponseOutput; - // (undocumented) - status: "200"; +export interface UsersCreateOptionalParams extends OperationOptions { } // @public -export interface UsersCreate409Response extends HttpResponse { - // (undocumented) - body: UserExistsResponseOutput; +export interface UsersOperations { // (undocumented) - status: "409"; -} - -// @public -export interface UsersCreate422Response extends HttpResponse { - // (undocumented) - body: InvalidUserResponseOutput; - // (undocumented) - status: "422"; -} - -// @public (undocumented) -export interface UsersCreateBodyParam { - // (undocumented) - body: { - user: User; - }; -} - -// @public (undocumented) -export type UsersCreateParameters = UsersCreateBodyParam & RequestParameters; - -// @public (undocumented) -export interface UsersForgotPassword { - post(options: UsersForgotPasswordParameters): StreamableMethod; -} - -// @public -export interface UsersForgotPassword200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public -export interface UsersForgotPassword404Response extends HttpResponse { - // (undocumented) - status: "404"; -} - -// @public (undocumented) -export interface UsersForgotPasswordBodyParam { - // (undocumented) - body: { - email: string; - }; -} - -// @public (undocumented) -export type UsersForgotPasswordParameters = UsersForgotPasswordBodyParam & RequestParameters; - -// @public (undocumented) -export interface UsersLogin { - // (undocumented) - post(options: UsersLoginParameters): StreamableMethod; -} - -// @public -export interface UsersLogin200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public -export interface UsersLogin401Response extends HttpResponse { - // (undocumented) - status: "401"; -} - -// @public (undocumented) -export interface UsersLoginBodyParam { - // (undocumented) - body: { + create: (user: User, options?: UsersCreateOptionalParams) => Promise<{ + id: number; username: string; - password: string; - }; -} - -// @public (undocumented) -export type UsersLoginParameters = UsersLoginBodyParam & RequestParameters; - -// @public (undocumented) -export interface UsersLogout { - // (undocumented) - get(options?: UsersLogoutParameters): StreamableMethod; -} - -// @public -export interface UsersLogout200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public (undocumented) -export type UsersLogoutParameters = RequestParameters; - -// @public (undocumented) -export interface UsersResetPassword { - // (undocumented) - get(options: UsersResetPasswordParameters): StreamableMethod; -} - -// @public -export interface UsersResetPassword200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public -export interface UsersResetPassword404Response extends HttpResponse { - // (undocumented) - status: "404"; -} - -// @public (undocumented) -export type UsersResetPasswordParameters = UsersResetPasswordQueryParam & RequestParameters; - -// @public (undocumented) -export interface UsersResetPasswordQueryParam { - // (undocumented) - queryParameters: UsersResetPasswordQueryParamProperties; -} - -// @public (undocumented) -export interface UsersResetPasswordQueryParamProperties { - // (undocumented) - resetToken: string; -} - -// @public (undocumented) -export interface UsersValidate { - // (undocumented) - get(options: UsersValidateParameters): StreamableMethod; -} - -// @public -export interface UsersValidate200Response extends HttpResponse { - // (undocumented) - status: "200"; -} - -// @public -export interface UsersValidate422Response extends HttpResponse { - // (undocumented) - body: InvalidUserResponseOutput; - // (undocumented) - status: "422"; -} - -// @public (undocumented) -export type UsersValidateParameters = UsersValidateQueryParam & RequestParameters; - -// @public (undocumented) -export interface UsersValidateQueryParam { - // (undocumented) - queryParameters: UsersValidateQueryParamProperties; -} - -// @public (undocumented) -export interface UsersValidateQueryParamProperties { - // (undocumented) - token: string; + email: string; + token: string; + }>; } // (No @packageDocumentation comment for this package) diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsCreateUrlAttachmentSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsCreateUrlAttachmentSample.ts deleted file mode 100644 index b540b7c939..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsCreateUrlAttachmentSample.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation CreateUrlAttachment - * - * @summary call operation CreateUrlAttachment - */ -async function todoItemsAttachmentsCreateUrlAttachmentSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const itemId = 123; - const result = await client - .path("/items/{itemId}/attachments", itemId) - .post({ - body: { - contents: { description: "{Your description}", url: "{Your url}" }, - }, - contentType: "application/json", - }); - console.log(result); -} - -async function main() { - todoItemsAttachmentsCreateUrlAttachmentSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsListSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsListSample.ts deleted file mode 100644 index beef0d0418..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsAttachmentsListSample.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation List - * - * @summary call operation List - */ -async function todoItemsAttachmentsListSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const itemId = 123; - const result = await client.path("/items/{itemId}/attachments", itemId).get(); - console.log(result); -} - -async function main() { - todoItemsAttachmentsListSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsCreateJsonSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsCreateJsonSample.ts deleted file mode 100644 index dfb5abc41f..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsCreateJsonSample.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation CreateJson - * - * @summary call operation CreateJson - */ -async function todoItemsCreateJsonSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/items") - .post({ - body: { - item: { - id: 123, - title: "{Your title}", - ownedBy: 123, - description: "{Your description}", - status: "NotStarted", - labels: ["{Your labels}"], - }, - attachments: [{ description: "{Your description}", url: "{Your url}" }], - }, - contentType: "application/json", - }); - console.log(result); -} - -async function main() { - todoItemsCreateJsonSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsDeleteSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsDeleteSample.ts deleted file mode 100644 index a1111dc715..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsDeleteSample.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Delete - * - * @summary call operation Delete - */ -async function todoItemsDeleteSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const id = 123; - const result = await client.path("/items/{id}", id).delete(); - console.log(result); -} - -async function main() { - todoItemsDeleteSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsGetSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsGetSample.ts deleted file mode 100644 index 0c12a0af91..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsGetSample.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Get - * - * @summary call operation Get - */ -async function todoItemsGetSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const id = 123; - const result = await client.path("/items/{id}", id).get(); - console.log(result); -} - -async function main() { - todoItemsGetSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsListSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsListSample.ts deleted file mode 100644 index 4aa84c58c2..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsListSample.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation List - * - * @summary call operation List - */ -async function todoItemsListSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/items") - .get({ queryParameters: { limit: 123, offset: 123 } }); - console.log(result); -} - -async function main() { - todoItemsListSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsUpdateSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsUpdateSample.ts deleted file mode 100644 index eaba08b1b5..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/todoItemsUpdateSample.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Update - * - * @summary call operation Update - */ -async function todoItemsUpdateSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const id = 123; - const result = await client - .path("/items/{id}", id) - .patch({ - body: { - patch: { - title: "{Your title}", - ownedBy: 123, - description: "{Your description}", - status: "NotStarted", - }, - }, - contentType: "application/merge-patch+json", - }); - console.log(result); -} - -async function main() { - todoItemsUpdateSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersCreateSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersCreateSample.ts deleted file mode 100644 index e126e1b6a4..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersCreateSample.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Create - * - * @summary call operation Create - */ -async function usersCreateSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/users") - .post({ - body: { - user: { - username: "{Your username}", - email: "{Your email}", - password: "{Your password}", - }, - }, - }); - console.log(result); -} - -async function main() { - usersCreateSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersForgotPasswordSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersForgotPasswordSample.ts deleted file mode 100644 index 8521462a2e..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersForgotPasswordSample.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation ForgotPassword - * - * @summary call operation ForgotPassword - */ -async function usersForgotPasswordSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/forgot-password") - .post({ body: { email: "{Your email}" } }); - console.log(result); -} - -async function main() { - usersForgotPasswordSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLoginSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLoginSample.ts deleted file mode 100644 index cc4e4d5137..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLoginSample.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Login - * - * @summary call operation Login - */ -async function usersLoginSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/login") - .post({ - body: { username: "{Your username}", password: "{Your password}" }, - }); - console.log(result); -} - -async function main() { - usersLoginSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLogoutSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLogoutSample.ts deleted file mode 100644 index fe00592e66..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersLogoutSample.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Logout - * - * @summary call operation Logout - */ -async function usersLogoutSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client.path("/logout").get(); - console.log(result); -} - -async function main() { - usersLogoutSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersResetPasswordSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersResetPasswordSample.ts deleted file mode 100644 index 738cba6e6f..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersResetPasswordSample.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation ResetPassword - * - * @summary call operation ResetPassword - */ -async function usersResetPasswordSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/reset-password") - .get({ queryParameters: { resetToken: "{Your resetToken}" } }); - console.log(result); -} - -async function main() { - usersResetPasswordSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersValidateSample.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersValidateSample.ts deleted file mode 100644 index 0d6987e51e..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/samples-dev/usersValidateSample.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed under the MIT License. - -import createTodoClient from "@notabrand/todo-non-branded"; -import * as dotenv from "dotenv"; - -dotenv.config(); - -/** - * This sample demonstrates how to call operation Validate - * - * @summary call operation Validate - */ -async function usersValidateSample() { - const endpointParam = "{Your endpointParam}"; - const credential = { key: "{Your API key}" }; - const client = createTodoClient(endpointParam, credential); - const result = await client - .path("/validate") - .get({ queryParameters: { token: "{Your token}" } }); - console.log(result); -} - -async function main() { - usersValidateSample(); -} - -main().catch(console.error); diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/index.ts new file mode 100644 index 0000000000..ffa0471b5b --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/index.ts @@ -0,0 +1,17 @@ +// Licensed under the MIT License. + +export { + UsersCreateOptionalParams, + TodoItemsListOptionalParams, + TodoItemsCreateOptionalParams, + TodoItemsGetOptionalParams, + TodoItemsUpdateOptionalParams, + TodoItemsDeleteOptionalParams, + TodoItemsAttachmentsListOptionalParams, + TodoItemsAttachmentsCreateAttachmentOptionalParams, +} from "./options.js"; +export { + createTodo, + TodoContext, + TodoClientOptionalParams, +} from "./todoContext.js"; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/options.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/options.ts new file mode 100644 index 0000000000..b5f8dc2302 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/options.ts @@ -0,0 +1,40 @@ +// Licensed under the MIT License. + +import { OperationOptions } from "@typespec/ts-http-runtime"; +import { TodoAttachment } from "../models/models.js"; + +/** Optional parameters. */ +export interface UsersCreateOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface TodoItemsListOptionalParams extends OperationOptions { + /** The limit to the number of items */ + limit?: number; + /** The offset to start paginating at */ + offset?: number; +} + +/** Optional parameters. */ +export interface TodoItemsCreateOptionalParams extends OperationOptions { + contentType?: string; + attachments?: TodoAttachment[]; +} + +/** Optional parameters. */ +export interface TodoItemsGetOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface TodoItemsUpdateOptionalParams extends OperationOptions { + contentType?: string; +} + +/** Optional parameters. */ +export interface TodoItemsDeleteOptionalParams extends OperationOptions {} + +/** Optional parameters. */ +export interface TodoItemsAttachmentsListOptionalParams + extends OperationOptions {} + +/** Optional parameters. */ +export interface TodoItemsAttachmentsCreateAttachmentOptionalParams + extends OperationOptions {} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoContext.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoContext.ts new file mode 100644 index 0000000000..0b4e0c56d3 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoContext.ts @@ -0,0 +1,52 @@ +// Licensed under the MIT License. + +import { + Client, + ClientOptions, + getClient, + KeyCredential, + isKeyCredential, +} from "@typespec/ts-http-runtime"; + +export interface TodoContext extends Client {} + +/** Optional parameters for the client. */ +export interface TodoClientOptionalParams extends ClientOptions {} + +export function createTodo( + endpointParam: string, + credential: KeyCredential, + options: TodoClientOptionalParams = {}, +): TodoContext { + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentInfo = `azsdk-js-todo-non-branded/1.0.0-beta.1`; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-api ${userAgentInfo}` + : `azsdk-js-api ${userAgentInfo}`; + const { apiVersion: _, ...updatedOptions } = { + ...options, + userAgentOptions: { userAgentPrefix }, + }; + const clientContext = getClient( + options.endpoint ?? String(endpointParam), + undefined, + updatedOptions, + ); + + if (isKeyCredential(credential)) { + clientContext.pipeline.addPolicy({ + name: "customKeyCredentialPolicy", + sendRequest(request, next) { + request.headers.set("Authorization", "Bearer " + credential.key); + return next(request); + }, + }); + } + clientContext.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + if (options.apiVersion) { + console.warn( + "This client does not support client api-version, please change it at the operation level", + ); + } + return clientContext; +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/attachments/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/attachments/index.ts new file mode 100644 index 0000000000..de6f596f99 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/attachments/index.ts @@ -0,0 +1,93 @@ +// Licensed under the MIT License. + +import { + TodoContext as Client, + TodoItemsAttachmentsCreateAttachmentOptionalParams, + TodoItemsAttachmentsListOptionalParams, +} from "../../index.js"; +import { + TodoAttachment, + todoAttachmentSerializer, + PageTodoAttachment, + pageTodoAttachmentDeserializer, +} from "../../../models/models.js"; +import { + StreamableMethod, + PathUncheckedResponse, + createRestError, + operationOptionsToRequestParameters, +} from "@typespec/ts-http-runtime"; + +export function _listSend( + context: Client, + itemId: number, + options: TodoItemsAttachmentsListOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/items/{itemId}/attachments", itemId) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _listDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return pageTodoAttachmentDeserializer(result.body); +} + +export async function list( + context: Client, + itemId: number, + options: TodoItemsAttachmentsListOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _listSend(context, itemId, options); + return _listDeserialize(result); +} + +export function _createAttachmentSend( + context: Client, + itemId: number, + contents: TodoAttachment, + options: TodoItemsAttachmentsCreateAttachmentOptionalParams = { + requestOptions: {}, + }, +): StreamableMethod { + return context + .path("/items/{itemId}/attachments", itemId) + .post({ + ...operationOptionsToRequestParameters(options), + body: todoAttachmentSerializer(contents), + }); +} + +export async function _createAttachmentDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["204"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return; +} + +export async function createAttachment( + context: Client, + itemId: number, + contents: TodoAttachment, + options: TodoItemsAttachmentsCreateAttachmentOptionalParams = { + requestOptions: {}, + }, +): Promise { + const result = await _createAttachmentSend( + context, + itemId, + contents, + options, + ); + return _createAttachmentDeserialize(result); +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/index.ts new file mode 100644 index 0000000000..0ec78284b8 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/todoItems/index.ts @@ -0,0 +1,274 @@ +// Licensed under the MIT License. + +import { + TodoContext as Client, + TodoItemsCreateOptionalParams, + TodoItemsDeleteOptionalParams, + TodoItemsGetOptionalParams, + TodoItemsListOptionalParams, + TodoItemsUpdateOptionalParams, +} from "../index.js"; +import { + TodoPage, + todoPageDeserializer, + TodoItem, + TodoLabels, + todoLabelsSerializer, + todoAttachmentSerializer, + _createResponseDeserializer, + _getResponseDeserializer, + TodoItemPatch, + todoItemPatchSerializer, + _updateResponseDeserializer, +} from "../../models/models.js"; +import { + StreamableMethod, + PathUncheckedResponse, + createRestError, + operationOptionsToRequestParameters, +} from "@typespec/ts-http-runtime"; + +export function _listSend( + context: Client, + options: TodoItemsListOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/items") + .get({ + ...operationOptionsToRequestParameters(options), + queryParameters: { limit: options?.limit, offset: options?.offset }, + }); +} + +export async function _listDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return todoPageDeserializer(result.body); +} + +export async function list( + context: Client, + options: TodoItemsListOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _listSend(context, options); + return _listDeserialize(result); +} + +export function _createSend( + context: Client, + item: TodoItem, + options: TodoItemsCreateOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context.path("/items").post({ + ...operationOptionsToRequestParameters(options), + contentType: (options.contentType as any) ?? "application/json", + body: { + item: { + title: item["title"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + labels: !item["labels"] + ? item["labels"] + : todoLabelsSerializer(item["labels"]), + _dummy: item["dummy"], + }, + attachments: !options?.attachments + ? options?.attachments + : options?.attachments.map((p: any) => { + return todoAttachmentSerializer(p); + }), + }, + }); +} + +export async function _createDeserialize( + result: PathUncheckedResponse, +): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _createResponseDeserializer(result.body); +} + +export async function create( + context: Client, + item: TodoItem, + options: TodoItemsCreateOptionalParams = { requestOptions: {} }, +): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const result = await _createSend(context, item, options); + return _createDeserialize(result); +} + +export function _getSend( + context: Client, + id: number, + options: TodoItemsGetOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/items/{id}", id) + .get({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _getDeserialize(result: PathUncheckedResponse): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _getResponseDeserializer(result.body); +} + +export async function get( + context: Client, + id: number, + options: TodoItemsGetOptionalParams = { requestOptions: {} }, +): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const result = await _getSend(context, id, options); + return _getDeserialize(result); +} + +export function _updateSend( + context: Client, + id: number, + patch: TodoItemPatch, + options: TodoItemsUpdateOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/items/{id}", id) + .patch({ + ...operationOptionsToRequestParameters(options), + contentType: + (options.contentType as any) ?? "application/merge-patch+json", + body: todoItemPatchSerializer(patch), + }); +} + +export async function _updateDeserialize( + result: PathUncheckedResponse, +): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _updateResponseDeserializer(result.body); +} + +export async function update( + context: Client, + id: number, + patch: TodoItemPatch, + options: TodoItemsUpdateOptionalParams = { requestOptions: {} }, +): Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; +}> { + const result = await _updateSend(context, id, patch, options); + return _updateDeserialize(result); +} + +export function _$deleteSend( + context: Client, + id: number, + options: TodoItemsDeleteOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/items/{id}", id) + .delete({ ...operationOptionsToRequestParameters(options) }); +} + +export async function _$deleteDeserialize( + result: PathUncheckedResponse, +): Promise { + const expectedStatuses = ["204"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return; +} + +/** + * @fixme delete is a reserved word that cannot be used as an operation name. + * Please add @clientName("clientName") or @clientName("", "javascript") + * to the operation to override the generated name. + */ +export async function $delete( + context: Client, + id: number, + options: TodoItemsDeleteOptionalParams = { requestOptions: {} }, +): Promise { + const result = await _$deleteSend(context, id, options); + return _$deleteDeserialize(result); +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/users/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/users/index.ts new file mode 100644 index 0000000000..b2eb13a210 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/api/users/index.ts @@ -0,0 +1,57 @@ +// Licensed under the MIT License. + +import { TodoContext as Client, UsersCreateOptionalParams } from "../index.js"; +import { + User, + userSerializer, + _createResponse1Deserializer, +} from "../../models/models.js"; +import { + StreamableMethod, + PathUncheckedResponse, + createRestError, + operationOptionsToRequestParameters, +} from "@typespec/ts-http-runtime"; + +export function _createSend( + context: Client, + user: User, + options: UsersCreateOptionalParams = { requestOptions: {} }, +): StreamableMethod { + return context + .path("/users") + .post({ + ...operationOptionsToRequestParameters(options), + body: userSerializer(user), + }); +} + +export async function _createDeserialize( + result: PathUncheckedResponse, +): Promise<{ + id: number; + username: string; + email: string; + token: string; +}> { + const expectedStatuses = ["200"]; + if (!expectedStatuses.includes(result.status)) { + throw createRestError(result); + } + + return _createResponse1Deserializer(result.body); +} + +export async function create( + context: Client, + user: User, + options: UsersCreateOptionalParams = { requestOptions: {} }, +): Promise<{ + id: number; + username: string; + email: string; + token: string; +}> { + const result = await _createSend(context, user, options); + return _createDeserialize(result); +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/index.ts new file mode 100644 index 0000000000..56b66687ea --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/index.ts @@ -0,0 +1,5 @@ +// Licensed under the MIT License. + +export { TodoItemsOperations } from "./todoItems/index.js"; +export { UsersOperations } from "./users/index.js"; +export { TodoItemsAttachmentsOperations } from "./todoItems/attachments/index.js"; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/attachments/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/attachments/index.ts new file mode 100644 index 0000000000..d3a84179ae --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/attachments/index.ts @@ -0,0 +1,45 @@ +// Licensed under the MIT License. + +import { + TodoItemsAttachmentsListOptionalParams, + TodoItemsAttachmentsCreateAttachmentOptionalParams, +} from "../../../api/options.js"; +import { TodoContext } from "../../../api/todoContext.js"; +import { + list, + createAttachment, +} from "../../../api/todoItems/attachments/index.js"; +import { TodoAttachment, PageTodoAttachment } from "../../../models/models.js"; + +/** Interface representing a TodoItemsAttachments operations. */ +export interface TodoItemsAttachmentsOperations { + list: ( + itemId: number, + options?: TodoItemsAttachmentsListOptionalParams, + ) => Promise; + createAttachment: ( + itemId: number, + contents: TodoAttachment, + options?: TodoItemsAttachmentsCreateAttachmentOptionalParams, + ) => Promise; +} + +export function getTodoItemsAttachments(context: TodoContext) { + return { + list: (itemId: number, options?: TodoItemsAttachmentsListOptionalParams) => + list(context, itemId, options), + createAttachment: ( + itemId: number, + contents: TodoAttachment, + options?: TodoItemsAttachmentsCreateAttachmentOptionalParams, + ) => createAttachment(context, itemId, contents, options), + }; +} + +export function getTodoItemsAttachmentsOperations( + context: TodoContext, +): TodoItemsAttachmentsOperations { + return { + ...getTodoItemsAttachments(context), + }; +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/index.ts new file mode 100644 index 0000000000..c956c49970 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/todoItems/index.ts @@ -0,0 +1,114 @@ +// Licensed under the MIT License. + +import { + TodoItemsListOptionalParams, + TodoItemsCreateOptionalParams, + TodoItemsGetOptionalParams, + TodoItemsUpdateOptionalParams, + TodoItemsDeleteOptionalParams, +} from "../../api/options.js"; +import { TodoContext } from "../../api/todoContext.js"; +import { + list, + create, + get, + update, + $delete, +} from "../../api/todoItems/index.js"; +import { + TodoPage, + TodoItem, + TodoLabels, + TodoItemPatch, +} from "../../models/models.js"; +import { + TodoItemsAttachmentsOperations, + getTodoItemsAttachmentsOperations, +} from "./attachments/index.js"; + +/** Interface representing a TodoItems operations. */ +export interface TodoItemsOperations { + list: (options?: TodoItemsListOptionalParams) => Promise; + create: ( + item: TodoItem, + options?: TodoItemsCreateOptionalParams, + ) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; + get: ( + id: number, + options?: TodoItemsGetOptionalParams, + ) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; + update: ( + id: number, + patch: TodoItemPatch, + options?: TodoItemsUpdateOptionalParams, + ) => Promise<{ + id: number; + title: string; + createdBy: number; + assignedTo?: number; + description?: string; + status: "NotStarted" | "InProgress" | "Completed"; + createdAt: Date; + updatedAt: Date; + completedAt?: Date; + labels?: TodoLabels; + }>; + /** + * @fixme delete is a reserved word that cannot be used as an operation name. + * Please add @clientName("clientName") or @clientName("", "javascript") + * to the operation to override the generated name. + */ + delete: ( + id: number, + options?: TodoItemsDeleteOptionalParams, + ) => Promise; + attachments: TodoItemsAttachmentsOperations; +} + +export function getTodoItems(context: TodoContext) { + return { + list: (options?: TodoItemsListOptionalParams) => list(context, options), + create: (item: TodoItem, options?: TodoItemsCreateOptionalParams) => + create(context, item, options), + get: (id: number, options?: TodoItemsGetOptionalParams) => + get(context, id, options), + update: ( + id: number, + patch: TodoItemPatch, + options?: TodoItemsUpdateOptionalParams, + ) => update(context, id, patch, options), + delete: (id: number, options?: TodoItemsDeleteOptionalParams) => + $delete(context, id, options), + }; +} + +export function getTodoItemsOperations( + context: TodoContext, +): TodoItemsOperations { + return { + ...getTodoItems(context), + attachments: getTodoItemsAttachmentsOperations(context), + }; +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/users/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/users/index.ts new file mode 100644 index 0000000000..36c6ab6f07 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/classic/users/index.ts @@ -0,0 +1,32 @@ +// Licensed under the MIT License. + +import { UsersCreateOptionalParams } from "../../api/options.js"; +import { TodoContext } from "../../api/todoContext.js"; +import { create } from "../../api/users/index.js"; +import { User } from "../../models/models.js"; + +/** Interface representing a Users operations. */ +export interface UsersOperations { + create: ( + user: User, + options?: UsersCreateOptionalParams, + ) => Promise<{ + id: number; + username: string; + email: string; + token: string; + }>; +} + +export function getUsers(context: TodoContext) { + return { + create: (user: User, options?: UsersCreateOptionalParams) => + create(context, user, options), + }; +} + +export function getUsersOperations(context: TodoContext): UsersOperations { + return { + ...getUsers(context), + }; +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/clientDefinitions.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/clientDefinitions.ts deleted file mode 100644 index 25a4fdd813..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/clientDefinitions.ts +++ /dev/null @@ -1,169 +0,0 @@ -// Licensed under the MIT License. - -import { - UsersCreateParameters, - UsersValidateParameters, - UsersLoginParameters, - UsersLogoutParameters, - UsersForgotPasswordParameters, - UsersResetPasswordParameters, - TodoItemsListParameters, - TodoItemsCreateJsonParameters, - TodoItemsCreateFormParameters, - TodoItemsGetParameters, - TodoItemsUpdateParameters, - TodoItemsDeleteParameters, - TodoItemsAttachmentsListParameters, - TodoItemsAttachmentsCreateUrlAttachmentParameters, - TodoItemsAttachmentsCreateFileAttachmentParameters, -} from "./parameters.js"; -import { - UsersCreate200Response, - UsersCreate409Response, - UsersCreate422Response, - UsersValidate200Response, - UsersValidate422Response, - UsersLogin200Response, - UsersLogin401Response, - UsersLogout200Response, - UsersForgotPassword200Response, - UsersForgotPassword404Response, - UsersResetPassword200Response, - UsersResetPassword404Response, - TodoItemsList200Response, - TodoItemsCreateJson200Response, - TodoItemsCreateJson422Response, - TodoItemsCreateForm200Response, - TodoItemsCreateForm422Response, - TodoItemsGet200Response, - TodoItemsGet404Response, - TodoItemsUpdate200Response, - TodoItemsDelete200Response, - TodoItemsDelete404Response, - TodoItemsAttachmentsList200Response, - TodoItemsAttachmentsList404Response, - TodoItemsAttachmentsCreateUrlAttachment200Response, - TodoItemsAttachmentsCreateUrlAttachment404Response, - TodoItemsAttachmentsCreateFileAttachment200Response, - TodoItemsAttachmentsCreateFileAttachment404Response, -} from "./responses.js"; -import { Client, StreamableMethod } from "@typespec/ts-http-runtime"; - -export interface UsersCreate { - post( - options: UsersCreateParameters, - ): StreamableMethod< - UsersCreate200Response | UsersCreate409Response | UsersCreate422Response - >; -} - -export interface UsersValidate { - get( - options: UsersValidateParameters, - ): StreamableMethod; -} - -export interface UsersLogin { - post( - options: UsersLoginParameters, - ): StreamableMethod; -} - -export interface UsersLogout { - get( - options?: UsersLogoutParameters, - ): StreamableMethod; -} - -export interface UsersForgotPassword { - /** Sends a reset token to the user's email address */ - post( - options: UsersForgotPasswordParameters, - ): StreamableMethod< - UsersForgotPassword200Response | UsersForgotPassword404Response - >; -} - -export interface UsersResetPassword { - get( - options: UsersResetPasswordParameters, - ): StreamableMethod< - UsersResetPassword200Response | UsersResetPassword404Response - >; -} - -export interface TodoItemsList { - get( - options: TodoItemsListParameters, - ): StreamableMethod; - post( - options: TodoItemsCreateJsonParameters, - ): StreamableMethod< - TodoItemsCreateJson200Response | TodoItemsCreateJson422Response - >; - post( - options: TodoItemsCreateFormParameters, - ): StreamableMethod< - TodoItemsCreateForm200Response | TodoItemsCreateForm422Response - >; -} - -export interface TodoItemsGet { - get( - options?: TodoItemsGetParameters, - ): StreamableMethod; - patch( - options: TodoItemsUpdateParameters, - ): StreamableMethod; - delete( - options?: TodoItemsDeleteParameters, - ): StreamableMethod; -} - -export interface TodoItemsAttachmentsList { - get( - options?: TodoItemsAttachmentsListParameters, - ): StreamableMethod< - TodoItemsAttachmentsList200Response | TodoItemsAttachmentsList404Response - >; - post( - options: TodoItemsAttachmentsCreateUrlAttachmentParameters, - ): StreamableMethod< - | TodoItemsAttachmentsCreateUrlAttachment200Response - | TodoItemsAttachmentsCreateUrlAttachment404Response - >; - post( - options: TodoItemsAttachmentsCreateFileAttachmentParameters, - ): StreamableMethod< - | TodoItemsAttachmentsCreateFileAttachment200Response - | TodoItemsAttachmentsCreateFileAttachment404Response - >; -} - -export interface Routes { - /** Resource for '/users' has methods for the following verbs: post */ - (path: "/users"): UsersCreate; - /** Resource for '/validate' has methods for the following verbs: get */ - (path: "/validate"): UsersValidate; - /** Resource for '/login' has methods for the following verbs: post */ - (path: "/login"): UsersLogin; - /** Resource for '/logout' has methods for the following verbs: get */ - (path: "/logout"): UsersLogout; - /** Resource for '/forgot-password' has methods for the following verbs: post */ - (path: "/forgot-password"): UsersForgotPassword; - /** Resource for '/reset-password' has methods for the following verbs: get */ - (path: "/reset-password"): UsersResetPassword; - /** Resource for '/items' has methods for the following verbs: get, post */ - (path: "/items"): TodoItemsList; - /** Resource for '/items/\{id\}' has methods for the following verbs: get, patch, delete */ - (path: "/items/{id}", id: number): TodoItemsGet; - /** Resource for '/items/\{itemId\}/attachments' has methods for the following verbs: get, post */ - ( - path: "/items/{itemId}/attachments", - itemId: number, - ): TodoItemsAttachmentsList; -} - -export type TodoClient = Client & { - path: Routes; -}; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/helpers/serializerHelpers.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/helpers/serializerHelpers.ts new file mode 100644 index 0000000000..b968162a34 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/helpers/serializerHelpers.ts @@ -0,0 +1,39 @@ +// Licensed under the MIT License. + +export function serializeRecord< + T extends string | number | boolean | Date | null, + R, +>(item: Record): Record; +export function serializeRecord( + item: Record, + serializer: (item: T) => R, +): Record; +export function serializeRecord( + item: Record, + serializer?: (item: T) => R, +): Record { + return Object.keys(item).reduce( + (acc, key) => { + if (isSupportedRecordType(item[key])) { + acc[key] = item[key] as any; + } else if (serializer) { + const value = item[key]; + if (value !== undefined) { + acc[key] = serializer(value); + } + } else { + console.warn(`Don't know how to serialize ${item[key]}`); + acc[key] = item[key] as any; + } + return acc; + }, + {} as Record, + ); +} + +function isSupportedRecordType(t: any) { + return ( + ["number", "string", "boolean", "null"].includes(typeof t) || + t instanceof Date + ); +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/index.ts index b7675261df..4f53c4a4f4 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/index.ts +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/index.ts @@ -1,12 +1,31 @@ // Licensed under the MIT License. -import TodoClient from "./todoClient.js"; - -export * from "./todoClient.js"; -export * from "./parameters.js"; -export * from "./responses.js"; -export * from "./clientDefinitions.js"; -export * from "./models.js"; -export * from "./outputModels.js"; - -export default TodoClient; +export { TodoClient } from "./todoClient.js"; +export { + TodoPage, + TodoItem, + TodoLabels, + TodoLabelRecord, + TodoFileAttachment, + TodoUrlAttachment, + TodoAttachment, + TodoItemPatch, + PageTodoAttachment, + User, +} from "./models/index.js"; +export { + UsersCreateOptionalParams, + TodoItemsListOptionalParams, + TodoItemsCreateOptionalParams, + TodoItemsGetOptionalParams, + TodoItemsUpdateOptionalParams, + TodoItemsDeleteOptionalParams, + TodoItemsAttachmentsListOptionalParams, + TodoItemsAttachmentsCreateAttachmentOptionalParams, + TodoClientOptionalParams, +} from "./api/index.js"; +export { + TodoItemsOperations, + UsersOperations, + TodoItemsAttachmentsOperations, +} from "./classic/index.js"; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models.ts deleted file mode 100644 index 4afd20774f..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed under the MIT License. - -export interface User { - /** The user's username */ - username: string; - /** The user's email address */ - email: string; - /** - * The user's password, provided when creating a user - * but is otherwise not visible (and hashed by the backend) - */ - password: string; -} - -export interface TodoItem { - /** The item's unique id */ - id: number; - /** The item's title */ - title: string; - /** User that the todo is assigned to */ - ownedBy: number; - /** A longer description of the todo item in markdown format */ - description: string; - /** The status of the todo item */ - status: "NotStarted" | "InProgress" | "Completed"; - labels: TodoLabel[]; -} - -export interface TodoLabelRecord { - name: string; - color?: string; -} - -export interface TodoUrlAttachment { - /** A description of the URL */ - description: string; - /** The url */ - url: string; -} - -export interface TodoItemPatch { - /** The item's title */ - title?: string; - /** User that the todo is assigned to */ - ownedBy?: number; - /** A longer description of the todo item in markdown format */ - description?: string; - /** The status of the todo item */ - status?: "NotStarted" | "InProgress" | "Completed"; -} - -/** Alias for TodoLabel */ -export type TodoLabel = - | string - | string[] - | TodoLabelRecord - | Array; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/index.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/index.ts new file mode 100644 index 0000000000..1dfe6e9cdf --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/index.ts @@ -0,0 +1,14 @@ +// Licensed under the MIT License. + +export { + TodoPage, + TodoItem, + TodoLabels, + TodoLabelRecord, + TodoFileAttachment, + TodoUrlAttachment, + TodoAttachment, + TodoItemPatch, + PageTodoAttachment, + User, +} from "./models.js"; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/models.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/models.ts new file mode 100644 index 0000000000..70396054d5 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/models/models.ts @@ -0,0 +1,424 @@ +// Licensed under the MIT License. + +import { + uint8ArrayToString, + stringToUint8Array, +} from "@typespec/ts-http-runtime"; + +/** model interface TodoPage */ +export interface TodoPage { + /** The items in the page */ + items: TodoItem[]; + /** The number of items returned in this page */ + pageSize: number; + /** The total number of items */ + totalSize: number; + /** A link to the previous page, if it exists */ + prevLink?: string; + /** A link to the next page, if it exists */ + nextLink?: string; +} + +export function todoPageDeserializer(item: any): TodoPage { + return { + items: todoItemArrayDeserializer(item["items"]), + pageSize: item["pageSize"], + totalSize: item["totalSize"], + prevLink: item["prevLink"], + nextLink: item["nextLink"], + }; +} + +export function todoItemArraySerializer(result: Array): any[] { + return result.map((item) => { + return todoItemSerializer(item); + }); +} + +export function todoItemArrayDeserializer(result: Array): any[] { + return result.map((item) => { + return todoItemDeserializer(item); + }); +} + +/** model interface TodoItem */ +export interface TodoItem { + /** The item's unique id */ + readonly id: number; + /** The item's title */ + title: string; + /** User that created the todo */ + readonly createdBy: number; + /** User that the todo is assigned to */ + assignedTo?: number; + /** A longer description of the todo item in markdown format */ + description?: string; + /** The status of the todo item */ + status: "NotStarted" | "InProgress" | "Completed"; + /** When the todo item was created. */ + readonly createdAt: Date; + /** When the todo item was last updated */ + readonly updatedAt: Date; + /** When the todo item was makred as completed */ + readonly completedAt?: Date; + labels?: TodoLabels; + dummy?: string; +} + +export function todoItemSerializer(item: TodoItem): any { + return { + title: item["title"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + labels: !item["labels"] + ? item["labels"] + : todoLabelsSerializer(item["labels"]), + _dummy: item["dummy"], + }; +} + +export function todoItemDeserializer(item: any): TodoItem { + return { + id: item["id"], + title: item["title"], + createdBy: item["createdBy"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + createdAt: new Date(item["createdAt"]), + updatedAt: new Date(item["updatedAt"]), + completedAt: !item["completedAt"] + ? item["completedAt"] + : new Date(item["completedAt"]), + labels: !item["labels"] + ? item["labels"] + : todoLabelsDeserializer(item["labels"]), + dummy: item["_dummy"], + }; +} + +/** Alias for TodoLabels */ +export type TodoLabels = + | string + | string[] + | TodoLabelRecord + | TodoLabelRecord[]; + +export function todoLabelsSerializer(item: TodoLabels): any { + return item; +} + +export function todoLabelsDeserializer(item: any): TodoLabels { + return item; +} + +/** model interface TodoLabelRecord */ +export interface TodoLabelRecord { + name: string; + color?: string; +} + +export function todoLabelRecordSerializer(item: TodoLabelRecord): any { + return { name: item["name"], color: item["color"] }; +} + +export function todoLabelRecordDeserializer(item: any): TodoLabelRecord { + return { + name: item["name"], + color: item["color"], + }; +} + +export function todoLabelRecordArraySerializer( + result: Array, +): any[] { + return result.map((item) => { + return todoLabelRecordSerializer(item); + }); +} + +export function todoLabelRecordArrayDeserializer( + result: Array, +): any[] { + return result.map((item) => { + return todoLabelRecordDeserializer(item); + }); +} + +/** model interface TodoFileAttachment */ +export interface TodoFileAttachment { + /** The file name of the attachment */ + filename: string; + /** The media type of the attachment */ + mediaType: string; + /** The contents of the file */ + contents: Uint8Array; +} + +export function todoFileAttachmentSerializer(item: TodoFileAttachment): any { + return { + filename: item["filename"], + mediaType: item["mediaType"], + contents: uint8ArrayToString(item["contents"], "base64"), + }; +} + +export function todoFileAttachmentDeserializer(item: any): TodoFileAttachment { + return { + filename: item["filename"], + mediaType: item["mediaType"], + contents: + typeof item["contents"] === "string" + ? stringToUint8Array(item["contents"], "base64") + : item["contents"], + }; +} + +/** model interface TodoUrlAttachment */ +export interface TodoUrlAttachment { + /** A description of the URL */ + description: string; + /** The url */ + url: string; +} + +export function todoUrlAttachmentSerializer(item: TodoUrlAttachment): any { + return { description: item["description"], url: item["url"] }; +} + +export function todoUrlAttachmentDeserializer(item: any): TodoUrlAttachment { + return { + description: item["description"], + url: item["url"], + }; +} + +export function todoAttachmentArraySerializer( + result: Array, +): any[] { + return result.map((item) => { + return todoAttachmentSerializer(item); + }); +} + +export function todoAttachmentArrayDeserializer( + result: Array, +): any[] { + return result.map((item) => { + return todoAttachmentDeserializer(item); + }); +} + +/** Alias for TodoAttachment */ +export type TodoAttachment = TodoFileAttachment | TodoUrlAttachment; + +export function todoAttachmentSerializer(item: TodoAttachment): any { + return item; +} + +export function todoAttachmentDeserializer(item: any): TodoAttachment { + return item; +} + +/** model interface _CreateResponse */ +export interface _CreateResponse { + /** The item's unique id */ + readonly id: number; + /** The item's title */ + title: string; + /** User that created the todo */ + readonly createdBy: number; + /** User that the todo is assigned to */ + assignedTo?: number; + /** A longer description of the todo item in markdown format */ + description?: string; + /** The status of the todo item */ + status: "NotStarted" | "InProgress" | "Completed"; + /** When the todo item was created. */ + readonly createdAt: Date; + /** When the todo item was last updated */ + readonly updatedAt: Date; + /** When the todo item was makred as completed */ + readonly completedAt?: Date; + labels?: TodoLabels; +} + +export function _createResponseDeserializer(item: any): _CreateResponse { + return { + id: item["id"], + title: item["title"], + createdBy: item["createdBy"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + createdAt: new Date(item["createdAt"]), + updatedAt: new Date(item["updatedAt"]), + completedAt: !item["completedAt"] + ? item["completedAt"] + : new Date(item["completedAt"]), + labels: !item["labels"] + ? item["labels"] + : todoLabelsDeserializer(item["labels"]), + }; +} + +/** model interface _GetResponse */ +export interface _GetResponse { + /** The item's unique id */ + readonly id: number; + /** The item's title */ + title: string; + /** User that created the todo */ + readonly createdBy: number; + /** User that the todo is assigned to */ + assignedTo?: number; + /** A longer description of the todo item in markdown format */ + description?: string; + /** The status of the todo item */ + status: "NotStarted" | "InProgress" | "Completed"; + /** When the todo item was created. */ + readonly createdAt: Date; + /** When the todo item was last updated */ + readonly updatedAt: Date; + /** When the todo item was makred as completed */ + readonly completedAt?: Date; + labels?: TodoLabels; +} + +export function _getResponseDeserializer(item: any): _GetResponse { + return { + id: item["id"], + title: item["title"], + createdBy: item["createdBy"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + createdAt: new Date(item["createdAt"]), + updatedAt: new Date(item["updatedAt"]), + completedAt: !item["completedAt"] + ? item["completedAt"] + : new Date(item["completedAt"]), + labels: !item["labels"] + ? item["labels"] + : todoLabelsDeserializer(item["labels"]), + }; +} + +/** model interface TodoItemPatch */ +export interface TodoItemPatch { + /** The item's title */ + title?: string; + /** User that the todo is assigned to */ + assignedTo?: number | null; + /** A longer description of the todo item in markdown format */ + description?: string | null; + /** The status of the todo item */ + status?: "NotStarted" | "InProgress" | "Completed"; +} + +export function todoItemPatchSerializer(item: TodoItemPatch): any { + return { + title: item["title"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + }; +} + +/** model interface _UpdateResponse */ +export interface _UpdateResponse { + /** The item's unique id */ + readonly id: number; + /** The item's title */ + title: string; + /** User that created the todo */ + readonly createdBy: number; + /** User that the todo is assigned to */ + assignedTo?: number; + /** A longer description of the todo item in markdown format */ + description?: string; + /** The status of the todo item */ + status: "NotStarted" | "InProgress" | "Completed"; + /** When the todo item was created. */ + readonly createdAt: Date; + /** When the todo item was last updated */ + readonly updatedAt: Date; + /** When the todo item was makred as completed */ + readonly completedAt?: Date; + labels?: TodoLabels; +} + +export function _updateResponseDeserializer(item: any): _UpdateResponse { + return { + id: item["id"], + title: item["title"], + createdBy: item["createdBy"], + assignedTo: item["assignedTo"], + description: item["description"], + status: item["status"], + createdAt: new Date(item["createdAt"]), + updatedAt: new Date(item["updatedAt"]), + completedAt: !item["completedAt"] + ? item["completedAt"] + : new Date(item["completedAt"]), + labels: !item["labels"] + ? item["labels"] + : todoLabelsDeserializer(item["labels"]), + }; +} + +/** model interface PageTodoAttachment */ +export interface PageTodoAttachment { + items: TodoAttachment[]; +} + +export function pageTodoAttachmentDeserializer(item: any): PageTodoAttachment { + return { + items: todoAttachmentArrayDeserializer(item["items"]), + }; +} + +/** model interface User */ +export interface User { + /** An autogenerated unique id for the user */ + readonly id: number; + /** The user's username */ + username: string; + /** The user's email address */ + email: string; + /** + * The user's password, provided when creating a user + * but is otherwise not visible (and hashed by the backend) + */ + password: string; +} + +export function userSerializer(item: User): any { + return { + username: item["username"], + email: item["email"], + password: item["password"], + }; +} + +/** model interface _CreateResponse1 */ +export interface _CreateResponse1 { + /** An autogenerated unique id for the user */ + readonly id: number; + /** The user's username */ + username: string; + /** The user's email address */ + email: string; + /** The token to use to construct the validate email address url */ + token: string; +} + +export function _createResponse1Deserializer(item: any): _CreateResponse1 { + return { + id: item["id"], + username: item["username"], + email: item["email"], + token: item["token"], + }; +} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/outputModels.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/outputModels.ts deleted file mode 100644 index 17f8423696..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/outputModels.ts +++ /dev/null @@ -1,99 +0,0 @@ -// Licensed under the MIT License. - -export interface UserCreatedResponseOutput { - /** An autogenerated unique id for the user */ - readonly id: number; - /** The user's username */ - username: string; - /** The user's email address */ - email: string; - /** - * The user's password, provided when creating a user - * but is otherwise not visible (and hashed by the backend) - */ - password: string; - /** The token to use to construct the validate email address url */ - token: string; -} - -/** The user already exists */ -export interface UserExistsResponseOutput extends ErrorModelOutput {} - -export interface ErrorModelOutput { - /** A machine readable error code */ - code: string; - /** A human readable message */ - message: string; -} - -/** The user is invalid (e.g. forgot to enter email address) */ -export interface InvalidUserResponseOutput extends ErrorModelOutput {} - -export interface InvalidTodoItemOutput extends ErrorModelOutput {} - -export interface TodoPageOutput { - /** The items in the page */ - items: Array; - pagination: { - pageSize: number; - totalSize: number; - prevLink?: string; - nextLink?: string; - }; -} - -export interface TodoItemOutput { - /** The item's unique id */ - id: number; - /** The item's title */ - title: string; - /** User that created the todo */ - readonly createdBy: number; - /** User that the todo is assigned to */ - ownedBy: number; - /** A longer description of the todo item in markdown format */ - description: string; - /** The status of the todo item */ - status: "NotStarted" | "InProgress" | "Completed"; - /** When the todo item was created. */ - readonly createdAt: string; - /** When the todo item was last updated */ - readonly updatedAt: string; - /** When the todo item was makred as completed */ - readonly completedAt: string; - labels: TodoLabelOutput[]; -} - -export interface TodoLabelRecordOutput { - name: string; - color?: string; -} - -export interface TodoUrlAttachmentOutput { - /** A description of the URL */ - description: string; - /** The url */ - url: string; -} - -export interface TodoFileAttachmentOutput { - /** The todo item this is attached to */ - todoItemId: number; - /** The file name of the attachment */ - filename: string; - /** The media type of the attachment */ - mediaType: string; - /** The url where the attachment can be downloaded from */ - url: string; -} - -/** Alias for TodoLabelOutput */ -export type TodoLabelOutput = - | string - | string[] - | TodoLabelRecordOutput - | Array; -/** Alias for TodoAttachmentOutput */ -export type TodoAttachmentOutput = - | TodoFileAttachmentOutput - | TodoUrlAttachmentOutput; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/parameters.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/parameters.ts deleted file mode 100644 index 0643253522..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/parameters.ts +++ /dev/null @@ -1,153 +0,0 @@ -// Licensed under the MIT License. - -import { RequestParameters } from "@typespec/ts-http-runtime"; -import { User, TodoItem, TodoUrlAttachment, TodoItemPatch } from "./models.js"; - -export interface UsersCreateBodyParam { - body: { user: User }; -} - -export type UsersCreateParameters = UsersCreateBodyParam & RequestParameters; - -export interface UsersValidateQueryParamProperties { - token: string; -} - -export interface UsersValidateQueryParam { - queryParameters: UsersValidateQueryParamProperties; -} - -export type UsersValidateParameters = UsersValidateQueryParam & - RequestParameters; - -export interface UsersLoginBodyParam { - body: { username: string; password: string }; -} - -export type UsersLoginParameters = UsersLoginBodyParam & RequestParameters; -export type UsersLogoutParameters = RequestParameters; - -export interface UsersForgotPasswordBodyParam { - body: { email: string }; -} - -export type UsersForgotPasswordParameters = UsersForgotPasswordBodyParam & - RequestParameters; - -export interface UsersResetPasswordQueryParamProperties { - resetToken: string; -} - -export interface UsersResetPasswordQueryParam { - queryParameters: UsersResetPasswordQueryParamProperties; -} - -export type UsersResetPasswordParameters = UsersResetPasswordQueryParam & - RequestParameters; - -export interface TodoItemsListQueryParamProperties { - /** The limit to the number of items */ - limit: number; - /** The offset to start paginating at */ - offset: number; -} - -export interface TodoItemsListQueryParam { - queryParameters: TodoItemsListQueryParamProperties; -} - -export type TodoItemsListParameters = TodoItemsListQueryParam & - RequestParameters; - -export interface TodoItemsCreateJsonBodyParam { - body: { item: TodoItem; attachments: Array }; -} - -export interface TodoItemsCreateJsonMediaTypesParam { - contentType: "application/json"; -} - -export type TodoItemsCreateJsonParameters = TodoItemsCreateJsonMediaTypesParam & - TodoItemsCreateJsonBodyParam & - RequestParameters; - -export interface TodoItemsCreateFormBodyParam { - body: - | FormData - | Array< - | { name: "item"; body: TodoItem } - | { - name: "attachments"; - body: - | TodoUrlAttachment - | string - | Uint8Array - | ReadableStream - | NodeJS.ReadableStream - | File; - filename?: string; - contentType?: string; - } - >; -} - -export interface TodoItemsCreateFormMediaTypesParam { - contentType: "multipart/form-data"; -} - -export type TodoItemsCreateFormParameters = TodoItemsCreateFormMediaTypesParam & - TodoItemsCreateFormBodyParam & - RequestParameters; -export type TodoItemsGetParameters = RequestParameters; - -export interface TodoItemsUpdateBodyParam { - body: { patch: TodoItemPatch }; -} - -export interface TodoItemsUpdateMediaTypesParam { - contentType: "application/merge-patch+json"; -} - -export type TodoItemsUpdateParameters = TodoItemsUpdateMediaTypesParam & - TodoItemsUpdateBodyParam & - RequestParameters; -export type TodoItemsDeleteParameters = RequestParameters; -export type TodoItemsAttachmentsListParameters = RequestParameters; - -export interface TodoItemsAttachmentsCreateUrlAttachmentBodyParam { - body: { contents: TodoUrlAttachment }; -} - -export interface TodoItemsAttachmentsCreateUrlAttachmentMediaTypesParam { - contentType: "application/json"; -} - -export type TodoItemsAttachmentsCreateUrlAttachmentParameters = - TodoItemsAttachmentsCreateUrlAttachmentMediaTypesParam & - TodoItemsAttachmentsCreateUrlAttachmentBodyParam & - RequestParameters; - -export interface TodoItemsAttachmentsCreateFileAttachmentBodyParam { - body: - | FormData - | Array<{ - name: "contents"; - body: - | string - | Uint8Array - | ReadableStream - | NodeJS.ReadableStream - | File; - filename?: string; - contentType?: string; - }>; -} - -export interface TodoItemsAttachmentsCreateFileAttachmentMediaTypesParam { - contentType: "multipart/form-data"; -} - -export type TodoItemsAttachmentsCreateFileAttachmentParameters = - TodoItemsAttachmentsCreateFileAttachmentMediaTypesParam & - TodoItemsAttachmentsCreateFileAttachmentBodyParam & - RequestParameters; diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/responses.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/responses.ts deleted file mode 100644 index 7e056ca567..0000000000 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/responses.ts +++ /dev/null @@ -1,168 +0,0 @@ -// Licensed under the MIT License. - -import { HttpResponse } from "@typespec/ts-http-runtime"; -import { - UserCreatedResponseOutput, - UserExistsResponseOutput, - InvalidUserResponseOutput, - TodoPageOutput, - TodoItemOutput, - InvalidTodoItemOutput, - TodoAttachmentOutput, -} from "./outputModels.js"; - -/** The request has succeeded. */ -export interface UsersCreate200Response extends HttpResponse { - status: "200"; - body: UserCreatedResponseOutput; -} - -/** The user already exists */ -export interface UsersCreate409Response extends HttpResponse { - status: "409"; - body: UserExistsResponseOutput; -} - -/** The user is invalid (e.g. forgot to enter email address) */ -export interface UsersCreate422Response extends HttpResponse { - status: "422"; - body: InvalidUserResponseOutput; -} - -/** The request has succeeded. */ -export interface UsersValidate200Response extends HttpResponse { - status: "200"; -} - -/** The user is invalid (e.g. forgot to enter email address) */ -export interface UsersValidate422Response extends HttpResponse { - status: "422"; - body: InvalidUserResponseOutput; -} - -/** The request has succeeded. */ -export interface UsersLogin200Response extends HttpResponse { - status: "200"; -} - -/** Access is unauthorized. */ -export interface UsersLogin401Response extends HttpResponse { - status: "401"; -} - -/** The request has succeeded. */ -export interface UsersLogout200Response extends HttpResponse { - status: "200"; -} - -/** The request has succeeded. */ -export interface UsersForgotPassword200Response extends HttpResponse { - status: "200"; -} - -/** The server cannot find the requested resource. */ -export interface UsersForgotPassword404Response extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface UsersResetPassword200Response extends HttpResponse { - status: "200"; -} - -/** The server cannot find the requested resource. */ -export interface UsersResetPassword404Response extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface TodoItemsList200Response extends HttpResponse { - status: "200"; - body: TodoPageOutput; -} - -/** The request has succeeded. */ -export interface TodoItemsCreateJson200Response extends HttpResponse { - status: "200"; - body: TodoItemOutput; -} - -/** Client error */ -export interface TodoItemsCreateJson422Response extends HttpResponse { - status: "422"; - body: InvalidTodoItemOutput; -} - -/** The request has succeeded. */ -export interface TodoItemsCreateForm200Response extends HttpResponse { - status: "200"; - body: TodoItemOutput; -} - -/** Client error */ -export interface TodoItemsCreateForm422Response extends HttpResponse { - status: "422"; - body: InvalidTodoItemOutput; -} - -/** The request has succeeded. */ -export interface TodoItemsGet200Response extends HttpResponse { - status: "200"; - body: TodoItemOutput; -} - -/** The server cannot find the requested resource. */ -export interface TodoItemsGet404Response extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface TodoItemsUpdate200Response extends HttpResponse { - status: "200"; - body: TodoItemOutput; -} - -/** The request has succeeded. */ -export interface TodoItemsDelete200Response extends HttpResponse { - status: "200"; -} - -/** The server cannot find the requested resource. */ -export interface TodoItemsDelete404Response extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface TodoItemsAttachmentsList200Response extends HttpResponse { - status: "200"; - body: TodoAttachmentOutput[]; -} - -/** The server cannot find the requested resource. */ -export interface TodoItemsAttachmentsList404Response extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface TodoItemsAttachmentsCreateUrlAttachment200Response - extends HttpResponse { - status: "200"; -} - -/** The server cannot find the requested resource. */ -export interface TodoItemsAttachmentsCreateUrlAttachment404Response - extends HttpResponse { - status: "404"; -} - -/** The request has succeeded. */ -export interface TodoItemsAttachmentsCreateFileAttachment200Response - extends HttpResponse { - status: "200"; -} - -/** The server cannot find the requested resource. */ -export interface TodoItemsAttachmentsCreateFileAttachment404Response - extends HttpResponse { - status: "404"; -} diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/todoClient.ts b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/todoClient.ts index a57163ccc9..2f64cccfbf 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/todoClient.ts +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/src/todoClient.ts @@ -1,45 +1,44 @@ // Licensed under the MIT License. -import { getClient, ClientOptions } from "@typespec/ts-http-runtime"; -import { KeyCredential } from "@typespec/ts-http-runtime"; -import { TodoClient } from "./clientDefinitions.js"; +import { getUsersOperations, UsersOperations } from "./classic/users/index.js"; +import { + getTodoItemsOperations, + TodoItemsOperations, +} from "./classic/todoItems/index.js"; +import { + createTodo, + TodoContext, + TodoClientOptionalParams, +} from "./api/index.js"; +import { Pipeline, KeyCredential } from "@typespec/ts-http-runtime"; -/** The optional parameters for the client */ -export interface TodoClientOptions extends ClientOptions {} +export { TodoClientOptionalParams } from "./api/todoContext.js"; -/** - * Initialize a new instance of `TodoClient` - * @param endpointParam - The parameter endpointParam - * @param credentials - uniquely identify client credential - * @param options - the parameter for all optional parameters - */ -export default function createClient( - endpointParam: string, - credentials: KeyCredential, - options: TodoClientOptions = {}, -): TodoClient { - const endpointUrl = options.endpoint ?? options.baseUrl ?? `${endpointParam}`; - const userAgentInfo = `azsdk-js-todo-non-branded-rest/1.0.0-beta.1`; - const userAgentPrefix = - options.userAgentOptions && options.userAgentOptions.userAgentPrefix - ? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}` - : `${userAgentInfo}`; - options = { - ...options, - userAgentOptions: { - userAgentPrefix, - }, - }; - const client = getClient(endpointUrl, options) as TodoClient; +export class TodoClient { + private _client: TodoContext; + /** The pipeline used by this client to make requests */ + public readonly pipeline: Pipeline; - client.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + constructor( + endpointParam: string, + credential: KeyCredential, + options: TodoClientOptionalParams = {}, + ) { + const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix; + const userAgentPrefix = prefixFromOptions + ? `${prefixFromOptions} azsdk-js-client` + : `azsdk-js-client`; + this._client = createTodo(endpointParam, credential, { + ...options, + userAgentOptions: { userAgentPrefix }, + }); + this.pipeline = this._client.pipeline; + this.users = getUsersOperations(this._client); + this.todoItems = getTodoItemsOperations(this._client); + } - client.pipeline.addPolicy({ - name: "customKeyCredentialPolicy", - async sendRequest(request, next) { - request.headers.set("Authorization", "Bearer " + credentials.key); - return next(request); - }, - }); - return client; + /** The operation groups for Users */ + public readonly users: UsersOperations; + /** The operation groups for TodoItems */ + public readonly todoItems: TodoItemsOperations; } diff --git a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/tsconfig.json b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/tsconfig.json index 4b2846c48c..031889db45 100644 --- a/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/tsconfig.json +++ b/packages/typespec-test/test/todo_non_branded/generated/typespec-ts/tsconfig.json @@ -17,8 +17,7 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "NodeNext", "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "paths": { "@notabrand/todo-non-branded": ["./src/index"] } + "esModuleInterop": true }, - "include": ["src/**/*.ts", "samples-dev/**/*.ts"] + "include": ["src/**/*.ts"] } diff --git a/packages/typespec-test/test/todo_non_branded/spec/main.tsp b/packages/typespec-test/test/todo_non_branded/spec/main.tsp index 1dd9dbc43e..fee9e1bdbe 100644 --- a/packages/typespec-test/test/todo_non_branded/spec/main.tsp +++ b/packages/typespec-test/test/todo_non_branded/spec/main.tsp @@ -1,15 +1,19 @@ import "@typespec/http"; import "@typespec/rest"; import "@typespec/openapi3"; - +import "@typespec/openapi"; +import "@typespec/json-schema"; using Http; +using JsonSchema; @service({ title: "Todo App", }) -@useAuth(BearerAuth) +@useAuth(BearerAuth | ApiKeyAuth) +@jsonSchema namespace Todo; +@jsonSchema model User { /** An autogenerated unique id for the user */ @key @@ -17,11 +21,12 @@ model User { id: safeint; /** The user's username */ + @minLength(2) @maxLength(50) username: string; /** The user's email address */ - //@format("email") + // @format("email") - crashes emitters for now email: string; /** @@ -30,11 +35,15 @@ model User { */ @visibility("create") password: string; + + /** Whether the user is validated. Never visible to the API. */ + @visibility("none") validated: boolean; } +@jsonSchema model TodoItem { /** The item's unique id */ - @key id: safeint; + @visibility("read") @key id: safeint; /** The item's title */ @maxLength(255) @@ -44,10 +53,10 @@ model TodoItem { @visibility("read") createdBy: User.id; /** User that the todo is assigned to */ - ownedBy: User.id; + assignedTo?: User.id; /** A longer description of the todo item in markdown format */ - description: string; + description?: string; /** The status of the todo item */ status: "NotStarted" | "InProgress" | "Completed"; @@ -59,24 +68,30 @@ model TodoItem { @visibility("read") updatedAt: utcDateTime; /** When the todo item was makred as completed */ - @visibility("read") completedAt: utcDateTime; + @visibility("read") completedAt?: utcDateTime; // Want the read form to be normalized to TodoLabelRecord[], but can't // https://github.com/microsoft/typespec/issues/2926 - labels: TodoLabel[]; + labels?: TodoLabels; + + // hack to get a different schema for create + // (fastify glue doesn't support readonly) + @visibility("create") _dummy?: string; } -union TodoLabel { +@jsonSchema +union TodoLabels { string, string[], TodoLabelRecord, TodoLabelRecord[], } +@jsonSchema model TodoLabelRecord { name: string; - //@format("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$") + @pattern("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$") color?: string; } @@ -85,6 +100,7 @@ union TodoAttachment { url: TodoUrlAttachment, } +@jsonSchema model TodoUrlAttachment { /** A description of the URL */ description: string; @@ -93,10 +109,8 @@ model TodoUrlAttachment { url: url; } +@jsonSchema model TodoFileAttachment { - /** The todo item this is attached to */ - todoItemId: TodoItem.id; - /** The file name of the attachment */ @maxLength(255) filename: string; @@ -104,19 +118,45 @@ model TodoFileAttachment { /** The media type of the attachment */ mediaType: string; - /** The url where the attachment can be downloaded from */ - url: url; + /** The contents of the file */ + contents: bytes; } +@jsonSchema @error -model Error { +model ApiError { /** A machine readable error code */ code: string; /** A human readable message */ + // https://github.com/microsoft/OpenAPI/blob/main/extensions/x-ms-primary-error-message.md + @OpenAPI.extension("x-ms-primary-error-message", true) message: string; } +/** + * Something is wrong with you. + */ +model Standard4XXResponse extends ApiError { + @minValue(400) + @maxValue(499) + @statusCode + statusCode: int32; +} + +/** + * Something is wrong with me. + */ +model Standard5XXResponse extends ApiError { + @minValue(500) + @maxValue(599) + @statusCode + statusCode: int32; +} + +alias WithStandardErrors = T | Standard4XXResponse | Standard5XXResponse; + +@useAuth(NoAuth) namespace Users { // would prefer to extend // https://github.com/microsoft/typespec/issues/2922 @@ -130,76 +170,53 @@ namespace Users { } /** The user already exists */ - model UserExistsResponse extends Error { + model UserExistsResponse extends ApiError { ...ConflictResponse; + code: "user-exists"; } /** The user is invalid (e.g. forgot to enter email address) */ - model InvalidUserResponse extends Error { + model InvalidUserResponse extends ApiError { @statusCode statusCode: 422; + code: "invalid-user"; } @route("/users") @post op create( - user: User, - ): { @bodyRoot _ : UserCreatedResponse; } | UserExistsResponse | InvalidUserResponse; - - @route("validate") - @get - op validate(@query token: string): OkResponse | InvalidUserResponse; - - @route("login") - @post - op login( - username: User.username, - password: User.password, - ): OkResponse | UnauthorizedResponse; - - @route("logout") - @get - op logout(): OkResponse; - - /** Sends a reset token to the user's email address */ - @route("forgot-password") - @post - op forgotPassword(email: User.email): OkResponse | NotFoundResponse; - - @route("reset-password") - @get - op resetPassword(@query resetToken: string): OkResponse | NotFoundResponse; + @body user: User, + ): WithStandardErrors; } @route("items") namespace TodoItems { model PaginationControls { /** The limit to the number of items */ - @query limit: int32 = 50; + @query limit?: int32 = 50; /** The offset to start paginating at */ - @query offset: int32 = 0; + @query offset?: int32 = 0; } model TodoPage { /** The items in the page */ - @pageItems - items: TodoItem[]; + @pageItems items: TodoItem[]; - pagination: { - /** The number of items returned in this page */ - pageSize: int32; + /** The number of items returned in this page */ + pageSize: int32; - /** The total number of items */ - totalSize: int32; + /** The total number of items */ + totalSize: int32; - ...PaginationControls; + ...PaginationControls; - /** A link to the previous page, if it exists */ - prevLink?: url; + /** A link to the previous page, if it exists */ + @prevLink + prevLink?: url; - /** A link to the next page, if it exists */ - nextLink?: url; - }; + /** A link to the next page, if it exists */ + @nextLink + nextLink?: url; } // deeply annoying that I have to copy/paste this... @@ -208,68 +225,59 @@ namespace TodoItems { title?: TodoItem.title; /** User that the todo is assigned to */ - ownedBy?: TodoItem.ownedBy; + assignedTo?: TodoItem.assignedTo | null; /** A longer description of the todo item in markdown format */ - description?: TodoItem.description; + description?: TodoItem.description | null; /** The status of the todo item */ status?: "NotStarted" | "InProgress" | "Completed"; } - model InvalidTodoItem extends Error { + model InvalidTodoItem extends ApiError { @statusCode statusCode: 422; } - @list op list(...PaginationControls): TodoPage; + @error + model NotFoundErrorResponse { + @statusCode statusCode: 404; + code: "not-found"; + } - @sharedRoute - @post - op createJson( - @header contentType: "application/json", - item: TodoItem, - attachments: TodoUrlAttachment[], - ): TodoItem | InvalidTodoItem; + model Page { + @pageItems items: T[]; + } + + @list op list(...PaginationControls): WithStandardErrors; - @sharedRoute @post - op createForm( - @header contentType: "multipart/form-data", + op create( + @header contentType: "application/json", item: TodoItem, - attachments?: (TodoUrlAttachment | bytes)[], - ): TodoItem | InvalidTodoItem; + attachments?: TodoAttachment[], + ): WithStandardErrors; - @get op get(@path id: TodoItem.id): TodoItem | NotFoundResponse; + @get op get(@path id: TodoItem.id): TodoItem | NotFoundErrorResponse; @patch op update( @header contentType: "application/merge-patch+json", @path id: TodoItem.id, - patch: TodoItemPatch, + @body patch: TodoItemPatch, ): TodoItem; - @delete op delete(@path id: TodoItem.id): OkResponse | NotFoundResponse; + @delete op delete( + @path id: TodoItem.id, + ): WithStandardErrors; @route("{itemId}/attachments") namespace Attachments { - op list( - @path itemId: TodoItem.id, - ): TodoAttachment[] | NotFoundResponse; - - @sharedRoute - @post - op createUrlAttachment( - @header contentType: "application/json", + @list op list( @path itemId: TodoItem.id, - contents: TodoUrlAttachment, - ): OkResponse | NotFoundResponse; + ): WithStandardErrors | NotFoundErrorResponse>; @sharedRoute @post - op createFileAttachment( - @header contentType: "multipart/form-data", + op createAttachment( @path itemId: TodoItem.id, - contents: bytes, - ): OkResponse | NotFoundResponse; - - // disabled: https://github.com/microsoft/typespec/issues/2925 - // @delete op delete(@path itemId: TodoItem.id): OkResponse | NotFoundResponse; + @body contents: TodoAttachment, + ): WithStandardErrors; } -} +} \ No newline at end of file diff --git a/packages/typespec-test/test/todo_non_branded/tsp-output/@typespec/openapi3/openapi.yaml b/packages/typespec-test/test/todo_non_branded/tsp-output/@typespec/openapi3/openapi.yaml new file mode 100644 index 0000000000..3720d6ffe8 --- /dev/null +++ b/packages/typespec-test/test/todo_non_branded/tsp-output/@typespec/openapi3/openapi.yaml @@ -0,0 +1,595 @@ +openapi: 3.0.0 +info: + title: Todo App + version: 0.0.0 +tags: [] +paths: + /items: + get: + operationId: TodoItems_list + parameters: + - $ref: '#/components/parameters/TodoItems.PaginationControls.limit' + - $ref: '#/components/parameters/TodoItems.PaginationControls.offset' + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/TodoItems.TodoPage' + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + post: + operationId: TodoItems_create + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/TodoItem' + '422': + description: Client error + content: + application/json: + schema: + $ref: '#/components/schemas/TodoItems.InvalidTodoItem' + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + item: + $ref: '#/components/schemas/TodoItemCreate' + attachments: + type: array + items: + $ref: '#/components/schemas/TodoAttachment' + required: + - item + /items/{id}: + get: + operationId: TodoItems_get + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + readOnly: true + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/TodoItem' + '404': + description: The server cannot find the requested resource. + patch: + operationId: TodoItems_update + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + readOnly: true + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/TodoItem' + requestBody: + required: true + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/TodoItems.TodoItemPatch' + delete: + operationId: TodoItems_delete + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + readOnly: true + responses: + '204': + description: There is no content to send for this request, but the headers may be useful. + '404': + description: The server cannot find the requested resource. + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + /items/{itemId}/attachments: + get: + operationId: Attachments_list + parameters: + - name: itemId + in: path + required: true + schema: + type: integer + format: int64 + readOnly: true + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: '#/components/schemas/TodoAttachment' + '404': + description: The server cannot find the requested resource. + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + post: + operationId: Attachments_createAttachment + parameters: + - name: itemId + in: path + required: true + schema: + type: integer + format: int64 + readOnly: true + responses: + '204': + description: There is no content to send for this request, but the headers may be useful. + '404': + description: The server cannot find the requested resource. + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TodoAttachment' + /users: + post: + operationId: Users_create + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/Users.UserCreatedResponse' + '409': + description: The user already exists + content: + application/json: + schema: + $ref: '#/components/schemas/Users.UserExistsResponse' + '422': + description: The user is invalid (e.g. forgot to enter email address) + content: + application/json: + schema: + $ref: '#/components/schemas/Users.InvalidUserResponse' + 4XX: + description: Something is wrong with you. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard4XXResponse' + 5XX: + description: Something is wrong with me. + content: + application/json: + schema: + $ref: '#/components/schemas/Standard5XXResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + security: + - {} +security: + - BearerAuth: [] + - ApiKeyAuth: [] +components: + parameters: + TodoItems.PaginationControls.limit: + name: limit + in: query + required: false + description: The limit to the number of items + schema: + type: integer + format: int32 + default: 50 + explode: false + TodoItems.PaginationControls.offset: + name: offset + in: query + required: false + description: The offset to start paginating at + schema: + type: integer + format: int32 + default: 0 + explode: false + schemas: + ApiError: + type: object + required: + - code + - message + properties: + code: + type: string + description: A machine readable error code + message: + type: string + description: A human readable message + x-ms-primary-error-message: true + Standard4XXResponse: + type: object + allOf: + - $ref: '#/components/schemas/ApiError' + description: Something is wrong with you. + Standard5XXResponse: + type: object + allOf: + - $ref: '#/components/schemas/ApiError' + description: Something is wrong with me. + TodoAttachment: + anyOf: + - $ref: '#/components/schemas/TodoFileAttachment' + - $ref: '#/components/schemas/TodoUrlAttachment' + TodoFileAttachment: + type: object + required: + - filename + - mediaType + - contents + properties: + filename: + type: string + maxLength: 255 + description: The file name of the attachment + mediaType: + type: string + description: The media type of the attachment + contents: + type: string + format: byte + description: The contents of the file + TodoItem: + type: object + required: + - id + - title + - createdBy + - status + - createdAt + - updatedAt + properties: + id: + type: integer + format: int64 + description: The item's unique id + readOnly: true + title: + type: string + maxLength: 255 + description: The item's title + createdBy: + type: integer + format: int64 + description: User that created the todo + readOnly: true + assignedTo: + type: integer + format: int64 + description: User that the todo is assigned to + readOnly: true + description: + type: string + description: A longer description of the todo item in markdown format + status: + type: string + enum: + - NotStarted + - InProgress + - Completed + description: The status of the todo item + createdAt: + type: string + format: date-time + description: When the todo item was created. + readOnly: true + updatedAt: + type: string + format: date-time + description: When the todo item was last updated + readOnly: true + completedAt: + type: string + format: date-time + description: When the todo item was makred as completed + readOnly: true + labels: + $ref: '#/components/schemas/TodoLabels' + TodoItemCreate: + type: object + required: + - title + - status + properties: + title: + type: string + maxLength: 255 + description: The item's title + assignedTo: + type: integer + format: int64 + description: User that the todo is assigned to + readOnly: true + description: + type: string + description: A longer description of the todo item in markdown format + status: + type: string + enum: + - NotStarted + - InProgress + - Completed + description: The status of the todo item + labels: + $ref: '#/components/schemas/TodoLabels' + _dummy: + type: string + TodoItems.InvalidTodoItem: + type: object + allOf: + - $ref: '#/components/schemas/ApiError' + TodoItems.TodoItemPatch: + type: object + properties: + title: + type: string + maxLength: 255 + description: The item's title + assignedTo: + type: integer + format: int64 + description: User that the todo is assigned to + readOnly: true + nullable: true + description: + type: string + description: A longer description of the todo item in markdown format + nullable: true + status: + type: string + enum: + - NotStarted + - InProgress + - Completed + description: The status of the todo item + TodoItems.TodoPage: + type: object + required: + - items + - pagination + properties: + items: + type: array + items: + $ref: '#/components/schemas/TodoItem' + description: The items in the page + pagination: + type: object + properties: + pageSize: + type: integer + format: int32 + description: The number of items returned in this page + totalSize: + type: integer + format: int32 + description: The total number of items + limit: + type: integer + format: int32 + description: The limit to the number of items + default: 50 + offset: + type: integer + format: int32 + description: The offset to start paginating at + default: 0 + prevLink: + type: string + format: uri + description: A link to the previous page, if it exists + nextLink: + type: string + format: uri + description: A link to the next page, if it exists + required: + - pageSize + - totalSize + TodoLabelRecord: + type: object + required: + - name + properties: + name: + type: string + color: + type: string + pattern: ^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$ + TodoLabels: + anyOf: + - type: string + - type: array + items: + type: string + - $ref: '#/components/schemas/TodoLabelRecord' + - type: array + items: + $ref: '#/components/schemas/TodoLabelRecord' + TodoUrlAttachment: + type: object + required: + - description + - url + properties: + description: + type: string + description: A description of the URL + url: + type: string + format: uri + description: The url + User: + type: object + required: + - username + - email + - password + properties: + username: + type: string + minLength: 2 + maxLength: 50 + description: The user's username + email: + type: string + description: The user's email address + password: + type: string + description: |- + The user's password, provided when creating a user + but is otherwise not visible (and hashed by the backend) + Users.InvalidUserResponse: + type: object + required: + - code + properties: + code: + type: string + enum: + - invalid-user + allOf: + - $ref: '#/components/schemas/ApiError' + description: The user is invalid (e.g. forgot to enter email address) + Users.UserCreatedResponse: + type: object + required: + - id + - username + - email + - token + properties: + id: + type: integer + format: int64 + description: An autogenerated unique id for the user + readOnly: true + username: + type: string + minLength: 2 + maxLength: 50 + description: The user's username + email: + type: string + description: The user's email address + token: + type: string + description: The token to use to construct the validate email address url + Users.UserExistsResponse: + type: object + required: + - code + properties: + code: + type: string + enum: + - user-exists + allOf: + - $ref: '#/components/schemas/ApiError' + description: The user already exists + securitySchemes: + BearerAuth: + type: http + scheme: bearer + ApiKeyAuth: + type: apiKey + in: cookie + name: session-id diff --git a/packages/typespec-test/test/todo_non_branded/tspconfig.yaml b/packages/typespec-test/test/todo_non_branded/tspconfig.yaml index 9309d43416..a02fe83506 100644 --- a/packages/typespec-test/test/todo_non_branded/tspconfig.yaml +++ b/packages/typespec-test/test/todo_non_branded/tspconfig.yaml @@ -3,7 +3,7 @@ emit: - "@typespec/openapi3" options: "@azure-tools/typespec-ts": - isModularLibrary: false + isModularLibrary: true generateMetadata: true azureSdkForJs: false generateSample: true diff --git a/packages/typespec-ts/src/modular/buildCodeModel.ts b/packages/typespec-ts/src/modular/buildCodeModel.ts index c8eb6ff068..9f0c8e24c6 100644 --- a/packages/typespec-ts/src/modular/buildCodeModel.ts +++ b/packages/typespec-ts/src/modular/buildCodeModel.ts @@ -1591,6 +1591,8 @@ function emitType( return emitEnum(context, type); case "EnumMember": return emitEnumMember(context, type); + case "ModelProperty": + return emitType(context, type.type, options); default: throw Error(`Not supported ${type.kind}`); } diff --git a/packages/typespec-ts/src/modular/helpers/clientHelpers.ts b/packages/typespec-ts/src/modular/helpers/clientHelpers.ts index 80b35bb234..1dbfac8757 100644 --- a/packages/typespec-ts/src/modular/helpers/clientHelpers.ts +++ b/packages/typespec-ts/src/modular/helpers/clientHelpers.ts @@ -159,7 +159,12 @@ export function buildGetClientEndpointParam( onClientOnly: true }).find((x) => x.kind === "endpoint" || x.kind === "path"); if (endpointParam) { - return `options.endpoint ?? options.baseUrl ?? String(${getClientParameterName(endpointParam)})`; + if (dpgContext.rlcOptions?.flavor === "azure") { + return `options.endpoint ?? options.baseUrl ?? String(${getClientParameterName(endpointParam)})`; + } else { + // unbranded does not have the deprecated baseUrl parameter + return `options.endpoint ?? String(${getClientParameterName(endpointParam)})`; + } } } diff --git a/packages/typespec-ts/src/utils/modelUtils.ts b/packages/typespec-ts/src/utils/modelUtils.ts index c902935f96..eea560afa9 100644 --- a/packages/typespec-ts/src/utils/modelUtils.ts +++ b/packages/typespec-ts/src/utils/modelUtils.ts @@ -1743,7 +1743,14 @@ export function isSchemaProperty( const queryInfo = getQueryParamName(program, property); const pathInfo = getPathParamName(program, property); const statusCodeInfo = isStatusCode(program, property); - return !(headerInfo || queryInfo || pathInfo || statusCodeInfo); + const isNonVisibility = getVisibility(program, property)?.includes("none"); + return !( + headerInfo || + queryInfo || + pathInfo || + statusCodeInfo || + isNonVisibility + ); } export function getEffectiveSchemaType(