From 95ce4dcc1e89587ffb1beecd236d005fb234cd6d Mon Sep 17 00:00:00 2001 From: Jason G <41053218+gianghungtien@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:54:29 +0100 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#75389=20[dom-w?= =?UTF-8?q?ebcodecs]=20Align=20`AudioDataInit.data`=20with=20`lib.dom.d.ts?= =?UTF-8?q?`=20by=20@gianghungtien?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dom-webcodecs/test/dom-webcodecs-tests.ts | 30 +++++++++++++++++++ types/dom-webcodecs/tsconfig.json | 1 + types/dom-webcodecs/webcodecs.generated.d.ts | 5 +++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/types/dom-webcodecs/test/dom-webcodecs-tests.ts b/types/dom-webcodecs/test/dom-webcodecs-tests.ts index 567ea0e984a106..0c5f6d4c3695c7 100644 --- a/types/dom-webcodecs/test/dom-webcodecs-tests.ts +++ b/types/dom-webcodecs/test/dom-webcodecs-tests.ts @@ -266,6 +266,36 @@ new AudioData({ sampleRate: 48000, }); +// AudioDataInit.data is a plain BufferSource, as in the spec and in lib.dom.d.ts, so any +// ArrayBuffer-backed view is accepted alongside the ArrayBuffer itself. +// $ExpectType AudioData +new AudioData({ + data: new Uint8Array(1024), + timestamp: 100, + format: "f32", + numberOfChannels: 2, + numberOfFrames: 1, + sampleRate: 48000, +}); + +// $ExpectType AudioData +new AudioData({ + data: new DataView(audioBuffer), + timestamp: 100, + format: "f32", + numberOfChannels: 2, + numberOfFrames: 1, + sampleRate: 48000, +}); + +// copyTo, unlike AudioDataInit.data, is AllowShared in both the spec and lib.dom.d.ts, so a +// SharedArrayBuffer-backed destination is accepted here. Keeping the two apart is what stops +// this file from colliding with the lib.dom.d.ts declarations it merges into. +declare const sharedDestination: Uint8Array; + +// $ExpectType void +audioFrame.copyTo(sharedDestination, { planeIndex: 0 }); + // $ExpectType AudioData audioFrame.clone(); diff --git a/types/dom-webcodecs/tsconfig.json b/types/dom-webcodecs/tsconfig.json index 82ef03356d90c9..11004743f7243e 100644 --- a/types/dom-webcodecs/tsconfig.json +++ b/types/dom-webcodecs/tsconfig.json @@ -3,6 +3,7 @@ "module": "node16", "lib": [ "es6", + "es2017.sharedmemory", "dom" ], "noImplicitAny": true, diff --git a/types/dom-webcodecs/webcodecs.generated.d.ts b/types/dom-webcodecs/webcodecs.generated.d.ts index fd08e9b510e718..95d1cf78a0a78f 100644 --- a/types/dom-webcodecs/webcodecs.generated.d.ts +++ b/types/dom-webcodecs/webcodecs.generated.d.ts @@ -10,7 +10,10 @@ interface AudioDataCopyToOptions { } interface AudioDataInit { - data: AllowSharedBufferSource; + // The WebCodecs spec declares this as a plain `BufferSource`, and so does lib.dom.d.ts. + // Chromium's IDL marks it `[AllowShared]`, but declaring it as `AllowSharedBufferSource` + // here conflicts with the lib.dom.d.ts declaration once SharedArrayBuffer is in scope. + data: BufferSource; format: AudioSampleFormat; numberOfChannels: number; numberOfFrames: number; From d0c6ddfe0065a6e3b0323f0fb77b10bb431af5c4 Mon Sep 17 00:00:00 2001 From: Samuel Imfeld Date: Mon, 17 Aug 2026 20:58:51 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#75396=20Add=20?= =?UTF-8?q?options=20parameter=20to=20static=20Document.load=20by=20@simfe?= =?UTF-8?q?ld?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/forge-viewer/index.d.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/types/forge-viewer/index.d.ts b/types/forge-viewer/index.d.ts index 20400006d19720..a3d0496dbbdf8d 100644 --- a/types/forge-viewer/index.d.ts +++ b/types/forge-viewer/index.d.ts @@ -581,6 +581,7 @@ declare namespace Autodesk { successCallback: (doc: Document) => void, errorCallback: (errorCode: ErrorCodes, errorMsg: string, messages: any[]) => void, accessControlProperties?: any, + options?: object, ): void; downloadAecModelData(onFinished?: (data: any) => void): Promise; @@ -599,13 +600,6 @@ declare namespace Autodesk { getViewableItems(document: Document): void; getViewablePath(item: object, outLoadOptions?: object): string; getViewGeometry(item: object): object; - load( - documentId: string, - onSuccessCallback: () => void, - onErrorCallback: () => void, - accessControlProperties?: object, - options?: object, - ): void; requestThumbnailWithSecurity(data: string, onComplete: (err: Error, response: any) => void): void; } From 97ba786e647c0899a2dd6d1b6807896762e725fa Mon Sep 17 00:00:00 2001 From: Carlos Lima Date: Mon, 17 Aug 2026 16:46:36 -0300 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#75378=20[auto-?= =?UTF-8?q?generated]=20[pg]=20Add=20missing=20enableChannelBinding=20opti?= =?UTF-8?q?on=20by=20@carlosalbertolajr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Carlos Lima Co-authored-by: carlosalbertolajr --- types/pg/index.d.ts | 1 + types/pg/pg-tests.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/types/pg/index.d.ts b/types/pg/index.d.ts index d7465295206422..9700c723c78a9f 100644 --- a/types/pg/index.d.ts +++ b/types/pg/index.d.ts @@ -20,6 +20,7 @@ export interface ClientConfig { stream?: () => stream.Duplex | undefined; statement_timeout?: false | number | undefined; ssl?: boolean | ConnectionOptions | undefined; + enableChannelBinding?: boolean | undefined; sslnegotiation?: "postgres" | "direct" | undefined; query_timeout?: number | undefined; lock_timeout?: number | undefined; diff --git a/types/pg/pg-tests.ts b/types/pg/pg-tests.ts index 52205ab381b58f..e15ba8e868a358 100644 --- a/types/pg/pg-tests.ts +++ b/types/pg/pg-tests.ts @@ -38,6 +38,7 @@ const client = new Client({ password: "secretpassword!!", application_name: "DefinitelyTyped", keepAlive: true, + enableChannelBinding: true, ssl: true, sslnegotiation: "direct", pipeline: true, @@ -270,6 +271,7 @@ const pool = new Pool({ idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, keepAlive: false, + enableChannelBinding: true, lock_timeout: 5000, log: (...args) => { console.log.apply(console, args); From 17dca58e37396e1a7e89c6926ce3fc1477f63bd2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:24:25 -0700 Subject: [PATCH 4/6] Remove contributors with deleted accounts (#75394) Co-authored-by: typescript-automation[bot] <290192711+typescript-automation[bot]@users.noreply.github.com> --- types/fancade-editor/package.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/types/fancade-editor/package.json b/types/fancade-editor/package.json index f4be65a78d6e5e..f8f1ffe99a2a35 100644 --- a/types/fancade-editor/package.json +++ b/types/fancade-editor/package.json @@ -10,10 +10,5 @@ "devDependencies": { "@types/fancade-editor": "workspace:." }, - "owners": [ - { - "name": "Bricked", - "githubUsername": "brckd" - } - ] + "owners": [] } From 2a5a27101e87f604224dc8f16e99d2d322bb375c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:25:30 -0700 Subject: [PATCH 5/6] Bump the github-actions group across 2 directories with 1 update (#75372) Signed-off-by: dependabot[bot] --- .github/actions/setup-for-scripts/action.yml | 2 +- .github/workflows/CI.yml | 4 ++-- .github/workflows/pnpm-cache.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-for-scripts/action.yml b/.github/actions/setup-for-scripts/action.yml index 97ba50f274adbf..54b238d0d087e9 100644 --- a/.github/actions/setup-for-scripts/action.yml +++ b/.github/actions/setup-for-scripts/action.yml @@ -7,7 +7,7 @@ runs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '24' - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 with: run_install: | - args: [--filter, ., --filter, '{./scripts}...'] diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 19612e58bd357e..49a55cf22fcf85 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -39,7 +39,7 @@ jobs: with: node-version: '24' - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 - id: matrix run: | @@ -79,7 +79,7 @@ jobs: printf "Aborting: symlinks found:\n%s" "$symlinks"; exit 1 fi - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 - name: Get pnpm cache info id: pnpm-cache diff --git a/.github/workflows/pnpm-cache.yml b/.github/workflows/pnpm-cache.yml index 6278497ff7b7c9..457e774beed889 100644 --- a/.github/workflows/pnpm-cache.yml +++ b/.github/workflows/pnpm-cache.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '24' - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 - name: Get pnpm cache info id: pnpm-cache From 0033158730b59ee677defd32419646baadd1f755 Mon Sep 17 00:00:00 2001 From: Jayen Ashar Date: Tue, 18 Aug 2026 08:46:27 +1000 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#75397=20[share?= =?UTF-8?q?tribe-flex-sdk][sharetribe-flex-integration-sdk]=20Add=20file?= =?UTF-8?q?=20attachment=20types=20by=20@jayenashar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index.d.ts | 139 +++++++++++++++++- .../package.json | 2 +- .../sharetribe-flex-integration-sdk-tests.ts | 77 +++++++++- types/sharetribe-flex-sdk/index.d.ts | 97 ++++++++++-- .../sharetribe-flex-sdk-tests.ts | 67 ++++++++- 5 files changed, 364 insertions(+), 18 deletions(-) diff --git a/types/sharetribe-flex-integration-sdk/index.d.ts b/types/sharetribe-flex-integration-sdk/index.d.ts index 4d1e7814c28973..5c59ca03ce6600 100644 --- a/types/sharetribe-flex-integration-sdk/index.d.ts +++ b/types/sharetribe-flex-integration-sdk/index.d.ts @@ -95,6 +95,9 @@ export interface TransactionRelationships { messages?: { data: ResourceReference[]; }; + protectedFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -144,6 +147,9 @@ export interface UserRelationships { stripeAccount?: { data?: ResourceReference; }; + privateFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -198,6 +204,9 @@ export interface ListingRelationships { images?: { data: ResourceReference[]; }; + protectedFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -216,6 +225,7 @@ export interface Listing { export interface MessageAttributes { content: string; createdAt: string; + deleted?: boolean; } /** @@ -228,6 +238,9 @@ export interface MessageRelationships { sender: { data: ResourceReference; }; + publicFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -290,7 +303,8 @@ export interface File { } /** - * File attachment relationships. The `message` relationship is only present when the file is attached to a message. + * File attachment relationships. Exactly one of `message`, `listing` or `transaction` is present, + * naming the resource the file is attached to. */ export interface FileAttachmentRelationships { file: { @@ -299,21 +313,79 @@ export interface FileAttachmentRelationships { message?: { data: ResourceReference; }; + listing?: { + data: ResourceReference; + }; + transaction?: { + data: ResourceReference; + }; } /** - * File attachment resource (links a file to a transaction message) + * Visibility of a file attachment. `protected` and `private` files are readable only by the + * resource owner and marketplace operators; `protected` ones can additionally be revealed to + * transaction parties by a transaction process action. + */ +export type FileAttachmentScope = "public" | "protected" | "private"; + +/** + * File attachment resource (links a file to a message, listing or transaction) */ export interface FileAttachment { id: UUID; type: "fileAttachment"; attributes: { - scope: "public"; + scope: FileAttachmentScope; deleted: boolean; }; relationships: FileAttachmentRelationships; } +/** + * A file to attach, as accepted by the `protectedFileAttachments` and `privateFileAttachments` + * body parameters + */ +export interface FileAttachmentParam { + fileId: UUID | string; +} + +/** + * A presigned upload target returned by `integrationSdk.fileUploads.create()` + */ +export interface FileUpload { + id: UUID; + type: "fileUpload"; + attributes: { + fileId: UUID; + url: string; + method: string; + headers: Record; + expiresAt: string; + }; +} + +/** + * A short-lived download URL returned by `integrationSdk.fileDownloads.create()` + */ +export interface FileDownload { + id: UUID; + type: "fileDownload"; + attributes: { + fileId: UUID; + url: string; + expiresAt: string; + }; +} + +/** + * File metadata extracted by `file.metadata()`, suitable for `integrationSdk.files.create()` + */ +export interface FileMetadata { + name: string; + mimeType: string; + size: number; +} + /** * Event attributes */ @@ -581,6 +653,7 @@ export interface IntegrationSdk { protectedData?: Record; privateData?: Record; profileImageId?: UUID; + privateFileAttachments?: FileAttachmentParam[]; }, options?: PerRequestOptions, ) => Promise>; @@ -645,6 +718,7 @@ export interface IntegrationSdk { privateData?: Record; metadata?: Record; images?: Array; + protectedFileAttachments?: FileAttachmentParam[]; }, options?: PerRequestOptions & { include?: string[] }, ) => Promise>; @@ -664,6 +738,7 @@ export interface IntegrationSdk { privateData?: Record; metadata?: Record; images?: Array; + protectedFileAttachments?: FileAttachmentParam[]; }, options?: PerRequestOptions, ) => Promise>; @@ -854,6 +929,19 @@ export interface IntegrationSdk { & PaginationParams & BaseQueryParams, ) => Promise>; + /** + * Register a file with the Integration API (first step of the upload flow). The created + * file starts in the `pendingUpload` state. + */ + create: ( + params: { + ownerId: UUID | string; + name: string; + mimeType: string; + size: number; + }, + options?: PerRequestOptions, + ) => Promise>; }; fileAttachments: { @@ -866,12 +954,34 @@ export interface IntegrationSdk { ids?: Array; fileIds?: Array; messageId?: UUID | string; + listingId?: UUID | string; + transactionId?: UUID | string; } & PaginationParams & BaseQueryParams, ) => Promise>; }; + fileUploads: { + /** + * Request a presigned upload URL for a file in the `pendingUpload` state + */ + create: ( + params: { fileId: UUID | string }, + options?: PerRequestOptions, + ) => Promise>; + }; + + fileDownloads: { + /** + * Request a short-lived download URL for a file + */ + create: ( + params: { fileId: UUID | string }, + options?: PerRequestOptions, + ) => Promise>; + }; + /** * Revoke authentication token */ @@ -928,3 +1038,26 @@ export namespace util { */ const prodCommandLimiterConfig: unknown; } + +/** + * Helpers for the file upload flow + */ +export namespace file { + /** + * Extract the metadata needed for `integrationSdk.files.create()` from a `File` object. + * @param file - A `File` object, e.g. from an `` element + */ + function metadata(file: unknown): FileMetadata; + /** + * Upload a file directly to cloud storage using a presigned URL obtained from + * `integrationSdk.fileUploads.create()`. This bypasses the SDK interceptor pipeline. + * @returns A promise that resolves when the upload is complete + */ + function upload(params: { + url: string; + file: unknown; + method?: string; + headers?: Record; + onUploadProgress?: (progressEvent: unknown) => void; + }): Promise; +} diff --git a/types/sharetribe-flex-integration-sdk/package.json b/types/sharetribe-flex-integration-sdk/package.json index c740f577329982..0394f7f7c8ae7c 100644 --- a/types/sharetribe-flex-integration-sdk/package.json +++ b/types/sharetribe-flex-integration-sdk/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/sharetribe-flex-integration-sdk", - "version": "1.13.9999", + "version": "1.14.9999", "projects": [ "https://github.com/sharetribe/flex-integration-sdk-js" ], diff --git a/types/sharetribe-flex-integration-sdk/sharetribe-flex-integration-sdk-tests.ts b/types/sharetribe-flex-integration-sdk/sharetribe-flex-integration-sdk-tests.ts index c2b00c9012596e..0cf8072385d2d0 100644 --- a/types/sharetribe-flex-integration-sdk/sharetribe-flex-integration-sdk-tests.ts +++ b/types/sharetribe-flex-integration-sdk/sharetribe-flex-integration-sdk-tests.ts @@ -1,4 +1,4 @@ -import { createInstance, util } from "sharetribe-flex-integration-sdk"; +import { createInstance, file, FileAttachmentScope, util } from "sharetribe-flex-integration-sdk"; const sdk = createInstance({ clientId: "client-id", @@ -149,7 +149,80 @@ sdk.files.query({ sdk.fileAttachments.query({ messageId: "message-id", fileIds: ["file-id"], include: ["file"] }).then((response) => { const firstAttachment = response.data.data[0]; if (firstAttachment) { - const scope: "public" = firstAttachment.attributes.scope; + const scope: FileAttachmentScope = firstAttachment.attributes.scope; + } +}); + +// Attachments on listings and transactions can be filtered by their attaching resource +// (API changelog 2026-07-13) +sdk.fileAttachments.query({ listingId: "listing-id" }).then((response) => { + const firstAttachment = response.data.data[0]; + if (firstAttachment && firstAttachment.relationships.listing) { + const listingId: string = firstAttachment.relationships.listing.data.id.uuid; + } +}); +sdk.fileAttachments.query({ transactionId: "transaction-id", include: ["file"] }).then((response) => { + const totalItems: number | undefined = response.data.meta.totalItems; +}); + +// File upload flow: create the file record, get an upload URL, then PUT the bytes +// (added in integration-sdk 1.14) +declare const fileLike: unknown; +const fileMetadata = file.metadata(fileLike); +sdk.files.create({ + ownerId: "user-id", + name: fileMetadata.name, + mimeType: fileMetadata.mimeType, + size: fileMetadata.size, +}).then((response) => { + const fileId = response.data.data.id; + return sdk.fileUploads.create({ fileId }).then((uploadResponse) => { + const upload = uploadResponse.data.data.attributes; + return file.upload({ + url: upload.url, + method: upload.method, + headers: upload.headers, + file: fileLike, + }); + }); +}); + +// Download URLs are requested per file (added in integration-sdk 1.14) +sdk.fileDownloads.create({ fileId: "file-id" }, { expand: true }).then((response) => { + const url: string = response.data.data.attributes.url; +}); + +// Files can be attached to listings and read back as a relationship (API changelog 2026-07-13) +sdk.listings.update({ + id: "listing-id", + protectedFileAttachments: [{ fileId: "file-id" }], +}).then((response) => { + const listingId: string = response.data.data.id.uuid; +}); +sdk.listings.show({ id: "listing-id", include: ["protectedFileAttachments.file"] }).then((response) => { + const attachments = response.data.data.relationships?.protectedFileAttachments; + if (attachments) { + const attachmentId: string = attachments.data[0].id.uuid; + } +}); + +// Users carry private file attachments, set through updateProfile (API changelog 2026-08-10) +sdk.users.updateProfile({ + id: "user-id", + privateFileAttachments: [{ fileId: "file-id" }], +}).then((response) => { + const userId: string = response.data.data.id.uuid; +}); + +// Messages expose their public attachments and a deleted flag (API changelog 2026-03-25, 2026-05-25) +sdk.messages.query({ transactionId: "transaction-id", include: ["publicFileAttachments.file"] }).then((response) => { + const firstMessage = response.data.data[0]; + if (firstMessage) { + const isDeleted: boolean | undefined = firstMessage.attributes.deleted; + const attachments = firstMessage.relationships.publicFileAttachments; + if (attachments) { + const attachmentId: string = attachments.data[0].id.uuid; + } } }); diff --git a/types/sharetribe-flex-sdk/index.d.ts b/types/sharetribe-flex-sdk/index.d.ts index d2514c8ba23b10..680cc3403082d9 100644 --- a/types/sharetribe-flex-sdk/index.d.ts +++ b/types/sharetribe-flex-sdk/index.d.ts @@ -211,6 +211,15 @@ export interface UserRelationships { }; } +/** + * Current user relationships. Private file attachments are readable only by the user themselves. + */ +export interface CurrentUserRelationships extends UserRelationships { + privateFileAttachments?: { + data: ResourceReference[]; + }; +} + /** * User resource */ @@ -237,9 +246,10 @@ export interface CurrentUserAttributes extends UserAttributes { /** * Current user resource */ -export interface CurrentUser extends Omit { +export interface CurrentUser extends Omit { type: "currentUser"; attributes: CurrentUserAttributes; + relationships?: CurrentUserRelationships; } /** @@ -311,11 +321,21 @@ export interface Listing { relationships?: ListingRelationships; } +/** + * Own listing relationships. Protected file attachments are readable only by the listing author. + */ +export interface OwnListingRelationships extends ListingRelationships { + protectedFileAttachments?: { + data: ResourceReference[]; + }; +} + /** * Own listing resource (has additional private fields) */ -export interface OwnListing extends Omit { +export interface OwnListing extends Omit { type: "ownListing"; + relationships?: OwnListingRelationships; } /** @@ -368,6 +388,9 @@ export interface TransactionRelationships { messages?: { data: ResourceReference[]; }; + protectedFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -407,6 +430,7 @@ export interface Booking { export interface MessageAttributes { content: string; createdAt: string; + deleted?: boolean; } /** @@ -416,6 +440,9 @@ export interface MessageRelationships { sender: { data: ResourceReference; }; + publicFileAttachments?: { + data: ResourceReference[]; + }; } /** @@ -629,6 +656,39 @@ export interface FileDownload { }; } +/** + * Visibility of a file attachment. `protected` and `private` files are readable only by the + * resource owner and marketplace operators; `protected` ones can additionally be revealed to + * transaction parties by a transaction process action. + */ +export type FileAttachmentScope = "public" | "protected" | "private"; + +/** + * A link between a file and the resource it is attached to. File attachments are read through + * relationships on the attaching resource rather than queried directly. + */ +export interface FileAttachment { + id: UUID; + type: "fileAttachment"; + attributes: { + scope: FileAttachmentScope; + deleted: boolean; + }; + relationships: { + file: { + data: ResourceReference; + }; + }; +} + +/** + * A file to attach, as accepted by the `publicFileAttachments`, `protectedFileAttachments` and + * `privateFileAttachments` body parameters + */ +export interface FileAttachmentParam { + fileId: UUID | string; +} + /** * File metadata extracted by `file.metadata()`, suitable for `sdk.ownFiles.create()` */ @@ -736,6 +796,7 @@ export interface MarketplaceSdk { protectedData?: Record; privateData?: Record; profileImageId?: UUID; + privateFileAttachments?: FileAttachmentParam[]; }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, @@ -757,10 +818,11 @@ export interface MarketplaceSdk { opts?: PerRequestOptions, ) => Promise>; /** - * Delete current user + * Delete current user. `deleteFromStripe` additionally deletes the associated Stripe + * Account and Stripe Customer, which requires the account to have a zero balance. */ delete: ( - params?: Record, + params?: { currentPassword?: string; deleteFromStripe?: boolean }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, ) => Promise>; @@ -896,6 +958,7 @@ export interface MarketplaceSdk { availabilityPlan?: unknown; publicData?: Record; privateData?: Record; + protectedFileAttachments?: FileAttachmentParam[]; }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, @@ -912,6 +975,7 @@ export interface MarketplaceSdk { availabilityPlan?: unknown; publicData?: Record; privateData?: Record; + protectedFileAttachments?: FileAttachmentParam[]; }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, @@ -945,6 +1009,7 @@ export interface MarketplaceSdk { availabilityPlan?: unknown; publicData?: Record; privateData?: Record; + protectedFileAttachments?: FileAttachmentParam[]; }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, @@ -1104,16 +1169,22 @@ export interface MarketplaceSdk { messages: { /** - * Query messages in a transaction + * Query messages. Either `transactionId` or `ids` must be provided. */ query: ( - params: { transactionId: UUID } & PaginationParams & BaseQueryParams, + params: + & ( + | { transactionId: UUID; ids?: Array } + | { transactionId?: UUID; ids: Array } + ) + & PaginationParams + & BaseQueryParams, ) => Promise>; /** * Send a message in a transaction */ send: ( - params: { transactionId: UUID; content: string }, + params: { transactionId: UUID; content: string; publicFileAttachments?: FileAttachmentParam[] }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, ) => Promise>; @@ -1293,9 +1364,12 @@ export interface MarketplaceSdk { files: { /** - * Show a file accessible to the current user + * Show a file accessible to the current user, identified by the ID of the file attachment + * that links it to the attaching resource */ - show: (params: { id: UUID | string } & BaseQueryParams) => Promise>; + show: ( + params: { fileAttachmentId: UUID | string } & BaseQueryParams, + ) => Promise>; }; fileUploads: { @@ -1322,10 +1396,11 @@ export interface MarketplaceSdk { fileDownloads: { /** - * Request a short-lived download URL for a file accessible to the current user + * Request a short-lived download URL for a file attached to a resource the current user + * has access to */ create: ( - params: { fileId: UUID | string }, + params: { fileAttachmentId: UUID | string }, queryParams?: { expand?: boolean }, opts?: PerRequestOptions, ) => Promise>; diff --git a/types/sharetribe-flex-sdk/sharetribe-flex-sdk-tests.ts b/types/sharetribe-flex-sdk/sharetribe-flex-sdk-tests.ts index 294e0f2b12838f..d8dc5f66dabbb5 100644 --- a/types/sharetribe-flex-sdk/sharetribe-flex-sdk-tests.ts +++ b/types/sharetribe-flex-sdk/sharetribe-flex-sdk-tests.ts @@ -1,6 +1,9 @@ import { createInstance, file, + FileAttachment, + FileAttachmentScope, + FileState, FileUpload, Marketplace, MutationResponse, @@ -35,10 +38,72 @@ sdk.ownFiles.create({ name: meta.name, mimeType: meta.mimeType, size: meta.size }, ); -sdk.fileDownloads.create({ fileId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }).then(response => { +// Files attached to another resource are reached through the attachment ID, not the file ID +sdk.fileDownloads.create({ fileAttachmentId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }).then(response => { const downloadUrl: string = response.data.data.attributes.url; }); +sdk.files.show({ fileAttachmentId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }).then(response => { + const state: FileState = response.data.data.attributes.state; +}); + +// Listings carry protected attachments readable by their author (API changelog 2026-07-13) +sdk.ownListings.create({ + title: "Bike", + protectedFileAttachments: [{ fileId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }], +}).then(response => { + const attachments = response.data.data.relationships?.protectedFileAttachments; + if (attachments) { + const attachmentId: string = attachments.data[0].id.uuid; + } +}); + +// Users carry private attachments, set through updateProfile (API changelog 2026-08-10) +sdk.currentUser.updateProfile({ + privateFileAttachments: [{ fileId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }], +}).then(response => { + const attachments = response.data.data.relationships?.privateFileAttachments; + if (attachments) { + const attachmentId: string = attachments.data[0].id.uuid; + } +}); + +// Messages take public attachments and can be queried by ids (API changelog 2026-03-25, 2026-05-25) +sdk.messages.send({ + transactionId: { _sdkType: "UUID", uuid: "b1b9e5f9-1a4a-4f0e-9d2f-0f3a3c1f2b7d" }, + content: "Here is the manual", + publicFileAttachments: [{ fileId: "a5d04285-07da-4fa0-b80b-ebabb8bac9e5" }], +}).then(response => { + const messageId: string = response.data.data.id.uuid; +}); + +sdk.messages.query({ ids: ["b1b9e5f9-1a4a-4f0e-9d2f-0f3a3c1f2b7d"], include: ["publicFileAttachments.file"] }).then( + response => { + const firstMessage = response.data.data[0]; + if (firstMessage) { + const isDeleted: boolean | undefined = firstMessage.attributes.deleted; + const attachments = firstMessage.relationships.publicFileAttachments; + if (attachments) { + const attachmentId: string = attachments.data[0].id.uuid; + } + } + // Attachments themselves arrive as included resources + const included = response.data.included ?? []; + const attachment = included.find(resource => resource.type === "fileAttachment") as + | FileAttachment + | undefined; + if (attachment) { + const scope: FileAttachmentScope = attachment.attributes.scope; + const fileId: string = attachment.relationships.file.data.id.uuid; + } + }, +); + +// Deleting the current user can cascade to Stripe (API changelog 2025-11-13) +sdk.currentUser.delete({ currentPassword: "hunter2", deleteFromStripe: true }).then(response => { + const status: number = response.status; +}); + // Query string utilities (added in flex-sdk 1.23) const qs: string = util.queryString({ ok: true }); const oqs: string = util.objectQueryString({ a: "foo", b: 150 });