From 7c1267482040a35ae911d51cb1cfc8ec9fa5d52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Nicol=C3=A1s=20Negro=20Caino?= Date: Fri, 25 Aug 2023 11:40:05 -0300 Subject: [PATCH] Refactor Moment Create Medias (#61) * move ts-node as dev-dependency * Add medias as optional create moment input --- .gitignore | 5 +- .../backend/src/methods/create_moment.ts | 10 ++- package.json | 6 +- packages/drops/package.json | 6 +- packages/moments/package.json | 6 +- .../moments/src/client/MomentsClient.spec.ts | 21 +++++- packages/moments/src/client/MomentsClient.ts | 75 +++++++++++++------ .../src/client/dtos/create/CreateInput.ts | 7 +- .../src/client/dtos/create/CreateMedia.ts | 4 + packages/performance/package.json | 2 +- packages/poaps/package.json | 6 +- packages/providers/package.json | 2 +- packages/utils/package.json | 4 +- yarn.lock | 16 ++-- 14 files changed, 113 insertions(+), 57 deletions(-) create mode 100644 packages/moments/src/client/dtos/create/CreateMedia.ts diff --git a/.gitignore b/.gitignore index 284f2a87..5a7a934d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ docs/.yarn/ !.yarn/versions .next .idea -.vscode \ No newline at end of file +.vscode + +# Ignore Typescript definitions file extension +*.d.ts diff --git a/examples/moments/backend/src/methods/create_moment.ts b/examples/moments/backend/src/methods/create_moment.ts index 9f58448f..76dac84b 100644 --- a/examples/moments/backend/src/methods/create_moment.ts +++ b/examples/moments/backend/src/methods/create_moment.ts @@ -1,4 +1,3 @@ -/* eslint-disable max-statements */ import { MomentsClient, CreateMomentInput } from '@poap-xyz/moments'; import fs from 'fs'; import mime from 'mime'; @@ -18,9 +17,14 @@ export const create_moment = async (client: MomentsClient): Promise => { * The Token ID related to the moment (Optional) */ tokenId: 6568008, - fileBinary: fileBuffer, author: '0x82AB2941Cf555CED5ad7Ed232a5B5f6083815FBC', - fileType: mimeType, + medias: [ + { + fileBinary: fileBuffer, + fileType: mimeType, + }, + ], + description: 'This is a description', }; try { diff --git a/package.json b/package.json index 528d3b1f..8b550739 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-typescript2": "^0.31.1", "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", "typedoc": "^0.23.28", "typescript": "^5.0.2" }, @@ -51,8 +52,5 @@ "packages/*", "examples/**" ], - "packageManager": "yarn@3.5.0", - "dependencies": { - "ts-node": "^10.9.1" - } + "packageManager": "yarn@3.5.0" } diff --git a/packages/drops/package.json b/packages/drops/package.json index 44562f95..8e0049ad 100644 --- a/packages/drops/package.json +++ b/packages/drops/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/drops", - "version": "0.0.35", + "version": "0.0.36", "description": "Drops module for the poap.js library", "main": "dist/cjs/index.cjs", "module": "dist/esm/index.mjs", @@ -26,7 +26,7 @@ "build": "rollup -c --bundleConfigAsCjs" }, "dependencies": { - "@poap-xyz/providers": "0.0.35", - "@poap-xyz/utils": "0.0.35" + "@poap-xyz/providers": "0.0.36", + "@poap-xyz/utils": "0.0.36" } } diff --git a/packages/moments/package.json b/packages/moments/package.json index f58595e8..a4b10e3c 100644 --- a/packages/moments/package.json +++ b/packages/moments/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/moments", - "version": "0.0.35", + "version": "0.0.36", "description": "Moments module for the poap.js library", "main": "dist/cjs/index.cjs", "module": "dist/esm/index.mjs", @@ -26,7 +26,7 @@ "build": "rollup -c --bundleConfigAsCjs" }, "dependencies": { - "@poap-xyz/providers": "0.0.35", - "@poap-xyz/utils": "0.0.35" + "@poap-xyz/providers": "0.0.36", + "@poap-xyz/utils": "0.0.36" } } diff --git a/packages/moments/src/client/MomentsClient.spec.ts b/packages/moments/src/client/MomentsClient.spec.ts index 88832e86..8432c032 100644 --- a/packages/moments/src/client/MomentsClient.spec.ts +++ b/packages/moments/src/client/MomentsClient.spec.ts @@ -13,6 +13,7 @@ describe('MomentsClient', () => { const FILE_TYPE = 'image/png'; const MEDIA_KEY = 'this-is-a-media-key'; const MEDIA_UPLOAD_URL = 'this-is-a-media-upload-url'; + const DESCRIPTION = 'This is a description'; let poapMomentsAPIMocked: MockProxy; let compassProviderMocked: MockProxy; @@ -34,10 +35,15 @@ describe('MomentsClient', () => { const inputs: CreateMomentInput = { dropId: DROP_ID, tokenId: TOKEN_ID, - fileBinary: FILE, - fileType: FILE_TYPE, + medias: [ + { + fileBinary: FILE, + fileType: FILE_TYPE, + }, + ], author: AUTHOR, onStepUpdate, + description: DESCRIPTION, }; poapMomentsAPIMocked.createMoment.mockResolvedValue({ id: MOMENT_ID, @@ -51,6 +57,14 @@ describe('MomentsClient', () => { url: MEDIA_UPLOAD_URL, }); + const EXPECTED_MOMENT_CREATE_INPUT = { + dropId: DROP_ID, + tokenId: TOKEN_ID, + author: AUTHOR, + description: DESCRIPTION, + mediaKeys: [MEDIA_KEY], + }; + // WHEN const moment = await client.createMoment(inputs); @@ -59,6 +73,9 @@ describe('MomentsClient', () => { expect(moment.author).toBe(AUTHOR); expect(moment.dropId).toBe(DROP_ID); expect(moment.tokenId).toBe(TOKEN_ID); + expect(poapMomentsAPIMocked.createMoment).toHaveBeenCalledWith( + EXPECTED_MOMENT_CREATE_INPUT, + ); expect(onStepUpdate).toHaveBeenCalledWith( CreateSteps.REQUESTING_MEDIA_UPLOAD_URL, ); diff --git a/packages/moments/src/client/MomentsClient.ts b/packages/moments/src/client/MomentsClient.ts index 38b550a1..4d994448 100644 --- a/packages/moments/src/client/MomentsClient.ts +++ b/packages/moments/src/client/MomentsClient.ts @@ -17,43 +17,46 @@ import { import { CreateMomentInput } from './dtos/create/CreateInput'; import { CreateSteps } from './dtos/create/CreateSteps'; import { FetchMomentsInput } from './dtos/fetch/FetchMomentsInput'; +import { CreateMedia } from './dtos/create/CreateMedia'; export class MomentsClient { + private static readonly DEFAULT_ON_STEP_UPDATE = (): void => { + //do nothing + }; + constructor( private poapMomentsApi: PoapMomentsApi, private CompassProvider: CompassProvider, ) {} public async createMoment(input: CreateMomentInput): Promise { - const defaultOnStepUpdate = (): void => { - //do nothing - }; - const onStepUpdate = input.onStepUpdate || defaultOnStepUpdate; - void onStepUpdate(CreateSteps.REQUESTING_MEDIA_UPLOAD_URL); - const { url, key } = await this.poapMomentsApi.getSignedUrl(); - void onStepUpdate(CreateSteps.UPLOADING_MEDIA); - await this.poapMomentsApi.uploadFile( - input.fileBinary, - url, - input.fileType, - input.onFileUploadProgress, - ); - void onStepUpdate(CreateSteps.UPLOADING_MEDIA_METADATA); - // we will be adding metadata to the media in the future - void onStepUpdate(CreateSteps.PROCESSING_MEDIA); - try { - await this.poapMomentsApi.waitForMediaProcessing(key, input.timeOut); - } catch (error) { - void onStepUpdate(CreateSteps.PROCESSING_MEDIA_ERROR); - throw error; + if (input.medias && input.medias.length > 1) { + // TODO: implement multiple medias + throw new Error('Multiple medias not supported yet'); + } + + const onStepUpdate = + input.onStepUpdate || MomentsClient.DEFAULT_ON_STEP_UPDATE; + + const mediaKeys: string[] = []; + if (input.medias && input.medias.length > 0) { + const media = input.medias[0]; + const key = await this.createMedia( + media, + onStepUpdate, + input.onFileUploadProgress, + input.timeOut, + ); + mediaKeys.push(key); } + void onStepUpdate(CreateSteps.UPLOADING_MOMENT); const response = await this.poapMomentsApi.createMoment({ dropId: input.dropId, author: input.author, - mediaKeys: [key], tokenId: input.tokenId, description: input.description, + mediaKeys, }); void onStepUpdate(CreateSteps.FINISHED); return new Moment( @@ -66,6 +69,34 @@ export class MomentsClient { ); } + private async createMedia( + media: CreateMedia, + onStepUpdate: (step: CreateSteps) => void | Promise, + onFileUploadProgress?: (progress: number) => void | Promise, + timeOut?: number, + ): Promise { + void onStepUpdate(CreateSteps.REQUESTING_MEDIA_UPLOAD_URL); + const { url, key } = await this.poapMomentsApi.getSignedUrl(); + void onStepUpdate(CreateSteps.UPLOADING_MEDIA); + await this.poapMomentsApi.uploadFile( + media.fileBinary, + url, + media.fileType, + onFileUploadProgress, + ); + void onStepUpdate(CreateSteps.UPLOADING_MEDIA_METADATA); + // we will be adding metadata to the media in the future + void onStepUpdate(CreateSteps.PROCESSING_MEDIA); + try { + await this.poapMomentsApi.waitForMediaProcessing(key, timeOut); + } catch (error) { + void onStepUpdate(CreateSteps.PROCESSING_MEDIA_ERROR); + throw error; + } + + return key; + } + async fetch({ limit, offset, diff --git a/packages/moments/src/client/dtos/create/CreateInput.ts b/packages/moments/src/client/dtos/create/CreateInput.ts index c9dd93e6..6ae1f308 100644 --- a/packages/moments/src/client/dtos/create/CreateInput.ts +++ b/packages/moments/src/client/dtos/create/CreateInput.ts @@ -1,21 +1,19 @@ import { CreateSteps } from './CreateSteps'; +import { CreateMedia } from './CreateMedia'; /** * Interface representing the input needed to create a moment. * @interface * @property {number} dropId - The ID of the drop related to the moment. * @property {number} [tokenId] - The ID of the token related to the moment (optional). - * @property {Uint8Array} fileBinary - The binary of the file to be uploaded. * @property {string} author - The author of the moment. An Ethereum address. * @property {string} description - The description of the moment (optional). * @property {string} timeOut - The amount of time to wait until media is processed. - * @property {string} fileType - The type of the file. * @property {(step: CreateSteps) => void | Promise} [onStepUpdate] - Optional callback function to be called when the step changes. * @property {(progress: number) => void | Promise} [onFileProgress] - Optional callback function to be called when the file upload progress change - progress is a number between 0 and 1. + * @property {CreateMedia[]} medias - The media to be uploaded. */ export interface CreateMomentInput { - fileBinary: Uint8Array; - fileType: string; author: string; description?: string; dropId: number; @@ -23,4 +21,5 @@ export interface CreateMomentInput { timeOut?: number; onStepUpdate?: (step: CreateSteps) => void | Promise; onFileUploadProgress?: (progress: number) => void | Promise; + medias?: CreateMedia[]; } diff --git a/packages/moments/src/client/dtos/create/CreateMedia.ts b/packages/moments/src/client/dtos/create/CreateMedia.ts new file mode 100644 index 00000000..5d922970 --- /dev/null +++ b/packages/moments/src/client/dtos/create/CreateMedia.ts @@ -0,0 +1,4 @@ +export interface CreateMedia { + fileBinary: Uint8Array; + fileType: string; +} diff --git a/packages/performance/package.json b/packages/performance/package.json index 2512cac8..408002aa 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/performance", - "version": "0.0.35", + "version": "0.0.36", "description": "Performance module for the poap.js library", "type": "module", "main": "dist/cjs/index.cjs", diff --git a/packages/poaps/package.json b/packages/poaps/package.json index 5ace7474..098921fb 100644 --- a/packages/poaps/package.json +++ b/packages/poaps/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/poaps", - "version": "0.0.35", + "version": "0.0.36", "description": "Poaps module for the poap.js library", "main": "dist/cjs/index.cjs", "module": "dist/esm/index.mjs", @@ -26,7 +26,7 @@ "build": "rollup -c --bundleConfigAsCjs" }, "dependencies": { - "@poap-xyz/providers": "0.0.35", - "@poap-xyz/utils": "0.0.35" + "@poap-xyz/providers": "0.0.36", + "@poap-xyz/utils": "0.0.36" } } diff --git a/packages/providers/package.json b/packages/providers/package.json index 5be51445..338a27ab 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/providers", - "version": "0.0.35", + "version": "0.0.36", "description": "Providers module for the poap.js library", "main": "dist/cjs/index.cjs", "module": "dist/esm/index.mjs", diff --git a/packages/utils/package.json b/packages/utils/package.json index 890190cb..8334bdc4 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/utils", - "version": "0.0.35", + "version": "0.0.36", "description": "Utils module for the poap.js library", "type": "module", "main": "dist/cjs/index.cjs", @@ -25,5 +25,5 @@ "scripts": { "build": "rollup -c --bundleConfigAsCjs" }, - "stableVersion": "0.0.35" + "stableVersion": "0.0.36" } diff --git a/yarn.lock b/yarn.lock index 3ae7ad95..a0a8ac40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -864,8 +864,8 @@ __metadata: version: 0.0.0-use.local resolution: "@poap-xyz/drops@workspace:packages/drops" dependencies: - "@poap-xyz/providers": 0.0.35 - "@poap-xyz/utils": 0.0.35 + "@poap-xyz/providers": 0.0.36 + "@poap-xyz/utils": 0.0.36 languageName: unknown linkType: soft @@ -873,8 +873,8 @@ __metadata: version: 0.0.0-use.local resolution: "@poap-xyz/moments@workspace:packages/moments" dependencies: - "@poap-xyz/providers": 0.0.35 - "@poap-xyz/utils": 0.0.35 + "@poap-xyz/providers": 0.0.36 + "@poap-xyz/utils": 0.0.36 languageName: unknown linkType: soft @@ -888,12 +888,12 @@ __metadata: version: 0.0.0-use.local resolution: "@poap-xyz/poaps@workspace:packages/poaps" dependencies: - "@poap-xyz/providers": 0.0.35 - "@poap-xyz/utils": 0.0.35 + "@poap-xyz/providers": 0.0.36 + "@poap-xyz/utils": 0.0.36 languageName: unknown linkType: soft -"@poap-xyz/providers@*, @poap-xyz/providers@0.0.35, @poap-xyz/providers@workspace:packages/providers": +"@poap-xyz/providers@*, @poap-xyz/providers@0.0.36, @poap-xyz/providers@workspace:packages/providers": version: 0.0.0-use.local resolution: "@poap-xyz/providers@workspace:packages/providers" dependencies: @@ -904,7 +904,7 @@ __metadata: languageName: unknown linkType: soft -"@poap-xyz/utils@*, @poap-xyz/utils@0.0.35, @poap-xyz/utils@workspace:packages/utils": +"@poap-xyz/utils@*, @poap-xyz/utils@0.0.36, @poap-xyz/utils@workspace:packages/utils": version: 0.0.0-use.local resolution: "@poap-xyz/utils@workspace:packages/utils" languageName: unknown