Tout ce que vous devez savoir sur les sièges pour douche senior

Prendre une douche peut devenir un défi pour les personnes âgées ou à mobilité réduite. C'est pourquoi les sièges pour douche senior sont devenus un accessoire indispensable pour assurer leur sécurité et leur confort. Dans cet article, nous vous guide  { "author_login": "noahdietz", "type": "pr_timeline", "title": "feat: generate apiary blueprint from proto protos", "url": "https://github.com/googleapis/gapic-generator-typescript/pull/590" }   { "type": "file", "path": "typescript/test/unit/apiary/blueprint.ts" }  1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import * as assert from 'assert'; 16 import * as blueprint from '../../../src/apiary/blueprint'; 17 18 describe('blueprint', () => { 19 it('should generate a blueprint', () => { 20 const bp = blueprint.generateBlueprint({ 21 info: { 22 title: 'Test API', 23 version: '0.1.0', 24 description: 'This is a test API', 25 }, 26 resources: { 27 products: { 28 methods: { 29 list: { 30 path: '/products', 31 description: 'Lists all products', 32 method: 'GET', 33 request: { 34 body: false, 35 queryParams: ['name', 'category'], 36 }, 37 response: { 38 body: { 39 type: 'object', 40 properties: { 41 products: { 42 type: 'array', 43 items: { 44 type: 'object', 45 properties: { 46 id: {type: 'string'}, 47 name: {type: 'string'}, 48 category: {type: 'string'}, 49 price: {type: 'number'}, 50 }, 51 }, 52 }, 53 }, 54 }, 55 }, 56 }, 57 }, 58 }, 59 }, 60 }); 61 assert.deepStrictEqual(bp, { 62 format: 'v10', 63 named: 'Test API', 64 version: '0.1.0', 65 metadata: { 66 description: 'This is a test API', 67 }, 68 routes: [ 69 { 70 name: 'List products', 71 description: 'Lists all products', 72 authenticated: false, 73 method: 'GET', 74 uri: '/products', 75 parameters: { 76 query: ['name', 'category'], 77 }, 78 requests: [ 79 { 80 body: { 81 schema: {}, 82 example: {}, 83 }, 84 }, 85 ], 86 responses: [ 87 { 88 status: 200, 89 body: { 90 schema: { 91 properties: { 92 products: 'array', 93 }, 94 }, 95 }, 96 }, 97 ], 98 }, 99 ]})})})  { "type": "file", "path": "typescript/src/apiary/blueprint.ts" }  1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import {SchemaObject} from './types'; 16 import {MethodKind} from '../utils'; 17 18 interface Blueprint { 19 format: 'v10'; 20 named: string; 21 version: string; 22 metadata: { 23 description?: string; 24 }; 25 routes: Route[]; 26 } 27 28 interface Route { 29 name: string; 30 description?: string; 31 authenticated: boolean; 32 method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; 33 uri: string; 34 parameters: { 35 query?: string[]; 36 path?: string[]; 37 header?: string[]; 38 }; 39 requests: { 40 body: { 41 schema: SchemaObject; 42 example?: unknown; 43 }; 44 }[]; 45 responses: { 46 status: number; 47 body: { 48 schema: SchemaObject; 49 example?: unknown; 50 }; 51 }[]; 52 } 53 54 interface GenerateApiaryInput { 55 info: { 56 title: string; 57 version: string; 58 description?: string; 59 }; 60 resources: { 61 [name: string]: { 62 methods: { 63 [name: string]: { 64 path: string; 65 description?: string; 66 method: MethodKind; 67 request: { 68 body: boolean; 69 queryParams?: string[]; 70 }; 71 response: { 72 body: SchemaObject; 73 }; 74 }; 75 }; 76 }; 77 }; 78 } 79 80 export function generateBlueprint(input: GenerateApiaryInput): Blueprint { 81 const {info, resources} = input; 82 const routes: Route[] = []; 83 84 for (const [resourceName, resource] of Object.entries(resources)) { 85 for (const [methodName, method] of Object.entries(resource.methods)) { 86 const route: Route = { 87 name: `${methodName} ${resourceName}`, 88 description: method.description, 89 authenticated: false, 90 method: method.method.toUpperCase() as Route['method'], 91 uri: method.path, 92 parameters: { 93 query: method.request.queryParams || [], 94 }, 95 requests: [ 96 { 97 body: { 98 schema: method.request.body ? method.response.body : {}, 99 example: {}, 100 }, 101 }, 102 ], 103 responses: [ 104 { 105 status: 200, 106 body: { 107 schema: method.response.body, 108 example: {}, 109 }, 110 }, 111 ], 112 }; 113 routes.push(route); 114 } 115 } 116 117 return { 118 format: 'v10', 119 named: info.title, 120 version: info.version, 121 metadata: { 122 description: info.description, 123 }, 124 routes, 125 }; 126 } 127 Author: noahdietz Date: Mon Feb 1 11:15:01 2021 -0800 feat: generate apiary blueprint from proto protos diff --git a/typescript/src/apiary/blueprint.ts b/typescript/src/apiary/blueprint.ts index 5f78b47f..78b47d9a 100644 --- a/typescript/src/apiary/blueprint.ts +++ b/typescript/src/apiary/blueprint.ts @@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import {SchemaObject} from './types'; -import {MethodKind} from '../utils'; +import {SchemaObject, TypeKind} from './types'; +import {MethodKind, ProtoMethod, ProtoService} from '../utils'; +import { APICall } from '../schema/calls'; +import { ProtoFile } from '../schema/files'; interface Blueprint { format: 'v10'; @@ -77,6 +79,78 @@ interface GenerateApiaryInput { }; } +export function generateBlueprintFromProtos(files: ProtoFile[]): Blueprint { + const info = { + title: 'API Blueprint', + version: '1.0.0', + description: 'API Blueprint generated from protos' + }; + + const resources: GenerateApiaryInput['resources'] = {}; + for (const file of files) { + for (const service of file.services) { + const methods: Record = {}; + for (const method of service.methods) { + const path = `/${service.name}/${method.name}`; + const request: APICall['request'] = method.requestType.kind === TypeKind.MESSAGE + ? { + body: true, + schema: schemaFromProtoType(method.requestType) + } + : { + body: false, + queryParams: method.kind === MethodKind.RPC + ? method.requestStreaming + ? ['stream_id'] + : [] + : [] + }; + const response: APICall['response'] = { + schema: schemaFromProtoType(method.responseType) + }; + methods[method.name] = { + path, + description: method.description, + method: method.kind, + request, + response + }; + } + const serviceName = service.name.split('.').pop()!; // remove package prefix + resources[serviceName] = { + methods + }; + } + } + + return generateBlueprint({ + info, + resources + }); +} + +function schemaFromProtoType(type: ProtoMethod['requestType'] | ProtoMethod['responseType']): SchemaObject { + return { + type: 'object', + properties: Object.fromEntries(type.fields.map(f => [f.name, { + type: fieldTypeToSchemaType(f.kind) + }])) + }; +} export function generateBlueprint(input: GenerateApiaryInput): Blueprint { const {info, resources} = input; const routes: Route[] = []; @@ -124,3 +198,18 @@ export function generateBlueprint(input: GenerateApiaryInput): Blueprint { routes, }; } + +function fieldTypeToSchemaType(kind: TypeKind): 'string' | 'number' | 'boolean' | 'array' { + switch(kind) { + case TypeKind.BOOL: + return 'boolean'; + case TypeKind.INT32: + case TypeKind.INT64: + case TypeKind.FLOAT: + case TypeKind.DOUBLE: + return 'number'; + case TypeKind.MESSAGE: + default: + return 'string'; // proto buffers do not have a native array type, so all are represented as strings + } +} \ No newline at end of file diff --git a/typescript/test/unit/apiary/blueprint.ts b/typescript/test/unit/apiary/blueprint.ts index a3ad0a03..44d31d5f 100644 --- a/typescript/test/unit/apiary/blueprint.ts +++ b/typescript/test/unit/apiary/blueprint.ts @@ -14,6 +14,8 @@ import * as assert from 'assert'; import * as blueprint from '../../../src/apiary/blueprint'; +import {ProtoMethod, ProtoService, ProtoType, MethodKind, TypeKind, ProtoField, ProtoFile} from '../../../src/utils'; +import {SchemaObject} from '../../../src/apiary/types'; describe('blueprint', () => { it('should generate a blueprint', () => { @@ -96,4 +98,104 @@ describe('blueprint', () => { ], }, ]})})}) + + it('generateBlueprintFromProtos', () => { + const files: ProtoFile[] = [ + { + name: 'test.proto', + package: 'test', + services: [ + { + name: 'TestService', + methods: [ + { + name: 'GetProduct', + kind: MethodKind.RPC, + requestType: { + kind: TypeKind.MESSAGE, + fields: [ + { name: 'id', kind: TypeKind.INT32 }, + { name: 'category', kind: TypeKind.STRING } + ] + }, + responseType: { + kind: TypeKind.MESSAGE, + fields: [ + { name: 'id', kind: TypeKind.INT32 }, + { name: 'name', kind: TypeKind.STRING }, + { name: 'price', kind: TypeKind.DOUBLE }, + ] + }, + requestStreaming: false, + responseStreaming: false, + description: 'Gets a product by ID' + }, + { + name: 'ListProducts', + kind: MethodKind.RPC, + requestType: { + kind: TypeKind.MESSAGE, + fields: [ + { name: 'category', kind: TypeKind.STRING }, + { name: 'max_results', kind: TypeKind.INT32 } + ] + }, + responseType: { + kind: TypeKind.MESSAGE, + fields: [ + { name: 'products', kind: TypeKind.MESSAGE, type: { + fields: [ + { name: 'id', kind: TypeKind.INT32 }, + { name: 'name', kind: TypeKind.STRING }, + { name: 'category', kind: TypeKind.STRING }, + { name: 'price',

Vidéo en Rapport

Prêt à donner vie à votre projet ?

Contactez-nous pour un devis gratuit et personnalisé.

Demander Mon Devis →