gpt4 book ai didi

typescript - 如何在环回 4.0 中使用存储组件?

转载 作者:行者123 更新时间:2023-12-01 10:19:40 24 4
gpt4 key购买 nike

我在环回 3.0 中使用存储组件来访问云存储。但我需要如何在环回 4.0 中实现。下面的链接使其在 3.0 中采样。

https://github.com/strongloop/loopback-example-storage

最佳答案

我将与社区分享我的实现,因为即使 Miroslav Bajtoš 的答案关键是要做到这一点,建议的文档不是很清楚,我引用了Calling other APIS and web services .

  • 首先我用 lb4 创建了一个新的数据源命令 cli 工具和我填写了 json文件的 key 与我在环回 3 数据源中使用的 key 相同。

  • // storage.datasource.ts

    import { inject } from '@loopback/core';
    import { juggler } from '@loopback/service-proxy';
    import * as config from './storage-gc.datasource.json';


    export class StorageGCDataSource extends juggler.DataSource {
    static dataSourceName = 'StorageGC';

    constructor(
    @inject('datasources.config.StorageGC', { optional: true })
    dsConfig: object = config,
    ) {
    super(dsConfig);
    }
    }
    // storage.datasource.json
    {
    "name": "Storage",
    "connector": "loopback-component-storage",
    "provider": "google",
    "keyFilename": "your-project-key.json",
    "projectId": "your-project-id",
    "nameConflict": "makeUnique"
    }
    // Note: your-project-key.json is in the root folder at the same level that tsconfig.json

    切记需要安装 环回组件存储 运行
    npm install --save loopback-component-storage
  • 第二名我用 lb4 创建了两个新模型命令 cli 工具。这些型号是:ContainerFile .

  • // container.model.ts

    import {Entity, model, property} from '@loopback/repository';

    @model()
    export class Container extends Entity {
    @property({
    type: 'string',
    required: true,
    })
    name: string;


    constructor(data?: Partial<Container>) {
    super(data);
    }
    }


    // file.model.ts

    import { Entity, model, property } from '@loopback/repository';

    @model()
    export class File extends Entity {
    @property({
    type: 'string',
    required: true,
    })
    name: string;

    @property({
    type: 'string',
    })
    type?: string;

    @property({
    type: 'string',
    })
    url?: string;


    constructor(data?: Partial<File>) {
    super(data);
    }
    }

  • 第三名我在 src/ 中创建了一个新文件夹名为 interfaces 的目录.在这个新文件夹中,我创建了一个 index.ts (主要遵循导出约定)和 storage.interface.ts (这是重要文件)

  • // index.ts

    export * from './storage.interface';

    // storage.interface.ts

    import { Container, File } from "../models";


    export type Callback<T> = (err: Error | null, reply: T) => void;

    export interface IStorageService {
    // container methods
    createContainer(container: Partial<Container>, cb: Callback<Container>): void;
    destroyContainer(containerName: string, cb: Callback<boolean>): void;
    getContainers(cb: Callback<Container[]>): void;
    getContainer(containerName: string, cb: Callback<Container>): void;
    // file methods
    getFiles(containerName: string, options: Object, cb: Callback<File[]>): void;
    getFile(containerName: string, fileName: string, cb: Callback<File>): void;
    removeFile(containerName: string, fileName: string, cb: Callback<boolean>): void;
    // main methods
    upload(containerName: string, req: any, res: any, options: Object, cb: Callback<any>): void;
    download(containerName: string, fileName: string, req: any, res: any, cb: Callback<any>): void;
    }
  • 第四名我创建了 container.controller.ts文件,但在此步骤之前您需要安装 @loopback/service-proxy 运行以下命令:
  • npm install --save @loopback/service-proxy
    // storage-gc.controller.ts

    import { inject } from '@loopback/core';
    import { serviceProxy } from '@loopback/service-proxy';
    import { post, requestBody, del, param, get, getFilterSchemaFor, Request, Response, RestBindings } from '@loopback/rest';
    import { Filter } from '@loopback/repository';
    import { promisify } from 'util';

    import { IStorageService } from '../interfaces';
    import { Container, File } from '../models';


    export class StorageGcController {
    @serviceProxy('StorageGC') // StorageGC is the name of the datasoruce
    private storageGcSvc: IStorageService;

    constructor(@inject(RestBindings.Http.REQUEST) public request: Request,
    @inject(RestBindings.Http.RESPONSE) public response: Response) { }

    @post('/containers', {
    responses: {
    '200': {
    description: 'Container model instance',
    content: { 'application/json': { schema: { 'x-ts-type': Container } } },
    },
    },
    })
    async createContainer(@requestBody() container: Container): Promise<Container> {
    const createContainer = promisify(this.storageGcSvc.createContainer);
    return await createContainer(container);
    }

    @get('/containers', {
    responses: {
    '200': {
    description: 'Array of Containers model instances',
    content: {
    'application/json': {
    schema: { type: 'array', items: { 'x-ts-type': Container } },
    },
    },
    },
    },
    })
    async findContainer(@param.query.object('filter', getFilterSchemaFor(Container)) filter?: Filter): Promise<Container[]> {
    const getContainers = promisify(this.storageGcSvc.getContainers);
    return await getContainers();
    }

    @get('/containers/{containerName}', {
    responses: {
    '200': {
    description: 'Container model instance',
    content: { 'application/json': { schema: { 'x-ts-type': Container } } },
    },
    },
    })
    async findContainerByName(@param.path.string('containerName') containerName: string): Promise<Container> {
    const getContainer = promisify(this.storageGcSvc.getContainer);
    return await getContainer(containerName);
    }

    @del('/containers/{containerName}', {
    responses: {
    '204': {
    description: 'Container DELETE success',
    },
    },
    })
    async deleteContainerByName(@param.path.string('containerName') containerName: string): Promise<boolean> {
    const destroyContainer = promisify(this.storageGcSvc.destroyContainer);
    return await destroyContainer(containerName);
    }

    @get('/containers/{containerName}/files', {
    responses: {
    '200': {
    description: 'Array of Files model instances belongs to container',
    content: {
    'application/json': {
    schema: { type: 'array', items: { 'x-ts-type': File } },
    },
    },
    },
    },
    })
    async findFilesInContainer(@param.path.string('containerName') containerName: string,
    @param.query.object('filter', getFilterSchemaFor(Container)) filter?: Filter): Promise<File[]> {
    const getFiles = promisify(this.storageGcSvc.getFiles);
    return await getFiles(containerName, {});
    }

    @get('/containers/{containerName}/files/{fileName}', {
    responses: {
    '200': {
    description: 'File model instances belongs to container',
    content: { 'application/json': { schema: { 'x-ts-type': File } } },
    },
    },
    })
    async findFileInContainer(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<File> {
    const getFile = promisify(this.storageGcSvc.getFile);
    return await getFile(containerName, fileName);
    }

    @del('/containers/{containerName}/files/{fileName}', {
    responses: {
    '204': {
    description: 'File DELETE from Container success',
    },
    },
    })
    async deleteFileInContainer(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<boolean> {
    const removeFile = promisify(this.storageGcSvc.removeFile);
    return await removeFile(containerName, fileName);
    }

    @post('/containers/{containerName}/upload', {
    responses: {
    '200': {
    description: 'Upload a Files model instances into Container',
    content: { 'application/json': { schema: { 'x-ts-type': File } } },
    },
    },
    })
    async upload(@param.path.string('containerName') containerName: string): Promise<File> {
    const upload = promisify(this.storageGcSvc.upload);
    return await upload(containerName, this.request, this.response, {});
    }

    @get('/containers/{containerName}/download/{fileName}', {
    responses: {
    '200': {
    description: 'Download a File within specified Container',
    content: { 'application/json': { schema: { 'x-ts-type': Object } } },
    },
    },
    })
    async download(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<any> {
    const download = promisify(this.storageGcSvc.download);
    return await download(containerName, fileName, this.request, this.response);
    }
    }

    通过此步骤,您的存储组件或最准确的连接器应该可以按预期工作。但是按照 Calling other APIS and web services的说明为集成测试改进此实现的指南您应该使用提供程序而不是 @serviceProxy Controller 中的装饰器,为此我创建了一个名为 providers 的新文件夹里面 src/包含以下两个文件的文件夹:

    // index.ts

    export * from './storage-service.provider';

    // storage-gc-service.provider.ts

    import { getService, juggler } from '@loopback/service-proxy';
    import { Provider } from '@loopback/core';
    import { StorageGCDataSource } from '../datasources/storage-gc.datasource';
    import { IStorageService } from '../interfaces';


    export class StorageGCServiceProvider implements Provider<IStorageService> {
    constructor(
    protected dataSource: juggler.DataSource = new StorageGCDataSource()

    /* I try to change the line above in the same way that documentation show,
    as follows:

    @inject('datasources.StorageGC')
    protected dataSource: juggler.DataSource = new StorageGCDataSource()

    and also, in the same way that repositories

    @inject('datasources.StorageGC')
    protected dataSource: StorageGCDataSource

    but always return:

    `Error: Cannot resolve injected arguments for StorageGCServiceProvider.[0]:
    The arguments[0] is not decorated for dependency injection, but a value is
    not supplied`
    */
    ) { }

    value(): Promise<IStorageService> {
    return getService(this.dataSource);
    }
    }

    之后,您需要修改您的 src/index.ts和您的 storage-gc.controller.ts通过以下方式

    // src/index.ts

    import { ApplicationConfig } from '@loopback/core';
    import { HocicosCuriososApp } from './application';
    import { StorageGCServiceProvider } from './providers';

    export { HocicosCuriososApp };

    export async function main(options: ApplicationConfig = {}) {
    const app = new HocicosCuriososApp(options);

    /* Add this line, it add a service to the app after that you can
    call them in the controller with dependency injection, like:
    @inject('services.StorageGCService') */
    app.serviceProvider(StorageGCServiceProvider);

    await app.boot();
    await app.start();

    const url = app.restServer.url;
    console.log(`Server is running at ${url}`);
    console.log(`Try ${url}/ping`);

    return app;
    }

    // storage-gc.controller.ts

    import { inject } from '@loopback/core';
    import { post, requestBody, del, param, get, getFilterSchemaFor, Request, Response, RestBindings } from '@loopback/rest';
    import { Filter } from '@loopback/repository';
    import { promisify } from 'util';

    import { IStorageService } from '../interfaces';
    import { Container, File } from '../models';


    export class StorageGcController {
    @inject('services.StorageGCService')
    private storageGcSvc: IStorageService;

    constructor(@inject(RestBindings.Http.REQUEST) public request: Request,
    @inject(RestBindings.Http.RESPONSE) public response: Response) { }

    @post('/containers', {
    responses: {
    '200': {
    description: 'Container model instance',
    content: { 'application/json': { schema: { 'x-ts-type': Container } } },
    },
    },
    })
    async createContainer(@requestBody() container: Container): Promise<Container> {
    const createContainer = promisify(this.storageGcSvc.createContainer);
    return await createContainer(container);
    }

    @get('/containers', {
    responses: {
    '200': {
    description: 'Array of Containers model instances',
    content: {
    'application/json': {
    schema: { type: 'array', items: { 'x-ts-type': Container } },
    },
    },
    },
    },
    })
    async findContainer(@param.query.object('filter', getFilterSchemaFor(Container)) filter?: Filter): Promise<Container[]> {
    const getContainers = promisify(this.storageGcSvc.getContainers);
    return await getContainers();
    }

    @get('/containers/{containerName}', {
    responses: {
    '200': {
    description: 'Container model instance',
    content: { 'application/json': { schema: { 'x-ts-type': Container } } },
    },
    },
    })
    async findContainerByName(@param.path.string('containerName') containerName: string): Promise<Container> {
    const getContainer = promisify(this.storageGcSvc.getContainer);
    return await getContainer(containerName);
    }

    @del('/containers/{containerName}', {
    responses: {
    '204': {
    description: 'Container DELETE success',
    },
    },
    })
    async deleteContainerByName(@param.path.string('containerName') containerName: string): Promise<boolean> {
    const destroyContainer = promisify(this.storageGcSvc.destroyContainer);
    return await destroyContainer(containerName);
    }

    @get('/containers/{containerName}/files', {
    responses: {
    '200': {
    description: 'Array of Files model instances belongs to container',
    content: {
    'application/json': {
    schema: { type: 'array', items: { 'x-ts-type': File } },
    },
    },
    },
    },
    })
    async findFilesInContainer(@param.path.string('containerName') containerName: string,
    @param.query.object('filter', getFilterSchemaFor(Container)) filter?: Filter): Promise<File[]> {
    const getFiles = promisify(this.storageGcSvc.getFiles);
    return await getFiles(containerName, {});
    }

    @get('/containers/{containerName}/files/{fileName}', {
    responses: {
    '200': {
    description: 'File model instances belongs to container',
    content: { 'application/json': { schema: { 'x-ts-type': File } } },
    },
    },
    })
    async findFileInContainer(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<File> {
    const getFile = promisify(this.storageGcSvc.getFile);
    return await getFile(containerName, fileName);
    }

    @del('/containers/{containerName}/files/{fileName}', {
    responses: {
    '204': {
    description: 'File DELETE from Container success',
    },
    },
    })
    async deleteFileInContainer(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<boolean> {
    const removeFile = promisify(this.storageGcSvc.removeFile);
    return await removeFile(containerName, fileName);
    }

    @post('/containers/{containerName}/upload', {
    responses: {
    '200': {
    description: 'Upload a Files model instances into Container',
    content: { 'application/json': { schema: { 'x-ts-type': File } } },
    },
    },
    })
    async upload(@param.path.string('containerName') containerName: string): Promise<File> {
    const upload = promisify(this.storageGcSvc.upload);
    return await upload(containerName, this.request, this.response, {});
    }

    @get('/containers/{containerName}/download/{fileName}', {
    responses: {
    '200': {
    description: 'Download a File within specified Container',
    content: { 'application/json': { schema: { 'x-ts-type': Object } } },
    },
    },
    })
    async download(@param.path.string('containerName') containerName: string,
    @param.path.string('fileName') fileName: string): Promise<any> {
    const download = promisify(this.storageGcSvc.download);
    return await download(containerName, fileName, this.request, this.response);
    }
    }

    就是这样,按照这些步骤,您必须使存储组件运行良好。祝你好运!

    问候。

    关于typescript - 如何在环回 4.0 中使用存储组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54663283/

    24 4 0