diff --git a/.changeset/proxy-use-stored-packagename.md b/.changeset/proxy-use-stored-packagename.md deleted file mode 100644 index 1b4271f..0000000 --- a/.changeset/proxy-use-stored-packagename.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@_linked/server-utils': patch ---- - -`LincdServerProxy.parseShape`: prefer the `packageName` stored on the shape constructor (set by `@_linked/core` during `linkedPackage()` registration) instead of extracting it from the URI. The URI form passes through `URI.sanitize` which is lossy (`@_linked/server` → `-_linked-server`), so the sanitized segment can't round-trip as a Node module specifier. Falls back to URI parsing for shapes predating the `packageName` property. - -Also: restore previously-deleted `src/types.d.ts` (CSS module declarations) needed by tsconfig. diff --git a/CHANGELOG.md b/CHANGELOG.md index a5ccbe4..2bc18b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # @\_linked/server-utils +## 1.0.5 + +### Patch Changes + +- [`6965162`](https://github.com/linked-cm/server-utils/commit/696516211de3a2a8b5b1f863f118b467c18330ee) - `LincdServerProxy.parseShape`: prefer the `packageName` stored on the shape constructor (set by `@_linked/core` during `linkedPackage()` registration) instead of extracting it from the URI. The URI form passes through `URI.sanitize` which is lossy (`@_linked/server` → `-_linked-server`), so the sanitized segment can't round-trip as a Node module specifier. Falls back to URI parsing for shapes predating the `packageName` property. + + Also: restore previously-deleted `src/types.d.ts` (CSS module declarations) needed by tsconfig. + ## 1.0.4 ### Patch Changes diff --git a/package.json b/package.json index dc6ab90..7f306a8 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "type": "git", "url": "" }, - "version": "1.0.4", + "version": "1.0.5", "linkedPackage": true, "main": "lib/cjs/index.js", "module": "lib/esm/index.js", diff --git a/src/backend.d.ts b/src/backend.d.ts new file mode 100644 index 0000000..0f3439c --- /dev/null +++ b/src/backend.d.ts @@ -0,0 +1,10 @@ +import './utils/BackendProvider.js'; +import './utils/ShapeProvider.js'; +import './utils/Upload.js'; +import { BackendProvider } from './utils/BackendProvider.js'; +import { UpdateMessage } from './utils/LinkedLiveUpdates.js'; +export declare class LincdServerUtilsBackendProvider extends BackendProvider { + setupBeforeControllers(): void; + setupLiveUpdatesMulticore(): void; + getUpdatesSince(timestamp: number, limit?: number): UpdateMessage[]; +} diff --git a/src/components/AppContext.d.ts b/src/components/AppContext.d.ts new file mode 100644 index 0000000..59b51ca --- /dev/null +++ b/src/components/AppContext.d.ts @@ -0,0 +1,14 @@ +import React from 'react'; +export declare const AppContext: React.Context; +export declare const useAppContext: () => AppContextProps; +export type AppContextProps = { + assets?: any; + isNativeApp?: boolean; + requestLD?: any; + requestObject?: any; + expressRequest?: any; + expressResponse?: any; + preloadScripts?: string[]; + preloadStyles?: string[]; +}; +export declare function AppContextProvider({ assets, isNativeApp, requestLD, requestObject, expressRequest, expressResponse, preloadScripts, preloadStyles, children, }: AppContextProps & React.PropsWithChildren): React.JSX.Element; diff --git a/src/components/AppRoot.d.ts b/src/components/AppRoot.d.ts new file mode 100644 index 0000000..571b357 --- /dev/null +++ b/src/components/AppRoot.d.ts @@ -0,0 +1,6 @@ +import React from 'react'; +export declare const AppRoot: React.NamedExoticComponent<{ + style?: any; +} & { + children?: React.ReactNode | undefined; +}>; diff --git a/src/components/Body.d.ts b/src/components/Body.d.ts new file mode 100644 index 0000000..c8ea523 --- /dev/null +++ b/src/components/Body.d.ts @@ -0,0 +1,10 @@ +import React from 'react'; +export declare const useCurrentPath: (appRoutes: any) => any; +export declare const Body: React.NamedExoticComponent<{ + children: any; + pageStyles?: any; + className?: any; + routes?: any; + style?: any; + loadingSpinner?: React.ReactNode; +}>; diff --git a/src/components/Head.d.ts b/src/components/Head.d.ts new file mode 100644 index 0000000..df290f0 --- /dev/null +++ b/src/components/Head.d.ts @@ -0,0 +1,2 @@ +import React from 'react'; +export declare const Head: ({ children }: React.PropsWithChildren) => React.JSX.Element; diff --git a/src/components/Html.d.ts b/src/components/Html.d.ts new file mode 100644 index 0000000..48eab62 --- /dev/null +++ b/src/components/Html.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +interface HtmlProps extends React.PropsWithChildren { + title: string; + customHead: any; + style?: React.CSSProperties; +} +export declare const Html: React.NamedExoticComponent; +export {}; diff --git a/src/components/Spinner.d.ts b/src/components/Spinner.d.ts new file mode 100644 index 0000000..6d6bf86 --- /dev/null +++ b/src/components/Spinner.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +interface SpinnerProps { + active?: boolean; + size?: 'small' | 'medium' | 'large'; + color?: string; + className?: string; +} +export declare function Spinner({ active, size, color, className, }: SpinnerProps): React.JSX.Element; +export default Spinner; diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..a0f549e --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,21 @@ +import './shapes/Lincd_API_Client.js'; +import './utils/Frontend.js'; +import './utils/JSONParser.js'; +import './utils/JSONWriter.js'; +import './utils/LincdServerProxy.js'; +import './utils/RequestData.js'; +import './utils/Server.js'; +import './utils/ImageResize.js'; +import './utils/ServerPaths.js'; +import './utils/LinkedEmail.js'; +import './utils/Backup.js'; +import './utils/LinkedLiveUpdates.js'; +import './components/Head.js'; +import './components/Body.js'; +import './components/AppRoot.js'; +import './components/Html.js'; +import './components/AppContext.js'; +import './components/Spinner.js'; +import './utils/ShapeIndex.js'; +export type { ShapeDetails, PropertyDetails, } from './types/ShapeDetails.js'; +export type { RouteConfig, RoutesConfig, RoutesModule, } from './types/RouteConfig.js'; diff --git a/src/ontologies/lincd-server-utils.d.ts b/src/ontologies/lincd-server-utils.d.ts new file mode 100644 index 0000000..58ef6e2 --- /dev/null +++ b/src/ontologies/lincd-server-utils.d.ts @@ -0,0 +1,33 @@ +/** + * Load the data of this ontology into memory, thus adding the properties of the entities of this ontology to the local graph. + */ +export declare var loadData: () => Promise<{ + "@context": { + dc: string; + owl: string; + rdf: string; + rdfs: string; + "lincd-server-utils": string; + }; + "@graph": { + "@id": string; + "@type": string; + "rdfs:comment": string; + "rdfs:isDefinedBy": { + "@id": string; + }; + "rdfs:label": string; + }[]; +}>; +/** + * The namespace of this ontology, which can be used to create NamedNodes with URI's not listed in this file + */ +export declare var ns: (term: string) => import("@_linked/core/utils/NodeReference.js").NodeReferenceValue; +/** + * The NamedNode of the ontology itself + */ +export declare var _self: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue; +export declare var Lincd_API_Client: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue; +export declare const lincdServerUtils: { + Lincd_API_Client: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue; +}; diff --git a/src/package.d.ts b/src/package.d.ts new file mode 100644 index 0000000..6166a27 --- /dev/null +++ b/src/package.d.ts @@ -0,0 +1,4 @@ +export declare const linkedShape: { + (constructor: T): void; + (config?: import("@_linked/core/utils/Package").ShapeConfig): (constructor: T) => void; +}, linkedUtil: (constructor: any) => any, linkedOntology: (allFileExports: any, nameSpace: (term: string) => import("@_linked/core/utils/NodeReference").NodeReferenceValue, suggestedPrefixAndFileName: string, loadDataFunction?: () => Promise, dataSource?: string | string[]) => void, registerPackageExport: (exportedObject: any) => void, packageExports: any, packageName: string; diff --git a/src/shapes/Lincd_API_Client.d.ts b/src/shapes/Lincd_API_Client.d.ts new file mode 100644 index 0000000..4185c6b --- /dev/null +++ b/src/shapes/Lincd_API_Client.d.ts @@ -0,0 +1,11 @@ +import { Shape } from '@_linked/core/shapes/Shape'; +export declare class Lincd_API_Client extends Shape { + static targetClass: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue; + static getFromURI(uri: string): Lincd_API_Client; + selectQuery(query: unknown): Promise; + updateQuery(query: unknown): Promise; + createQuery(query: unknown): Promise; + deleteQuery(query: unknown): Promise; + selectRaw(query: string): Promise; + private call; +} diff --git a/src/types/RouteConfig.d.ts b/src/types/RouteConfig.d.ts new file mode 100644 index 0000000..1c14f36 --- /dev/null +++ b/src/types/RouteConfig.d.ts @@ -0,0 +1,56 @@ +import React from 'react'; +/** + * Configuration for a single route in the application + */ +export interface RouteConfig { + /** + * The URL path pattern for this route (e.g. "/signin", "/data/:id") + * Supports React Router path syntax including params (:id) and wildcards (*) + */ + path: string; + /** + * Component for this route (can be lazy-loaded or eager) + * For lazy loading, use React.lazy(() => import('./Component')) with webpackChunkName comment + * For eager loading, import the component directly + */ + component?: React.LazyExoticComponent<() => JSX.Element> | React.ComponentType; + /** + * Custom render function for the route (alternative to component) + */ + render?: () => JSX.Element; + /** + * Whether this route requires authentication + * @default false + */ + requireAuth?: boolean; + /** + * Whether to exclude this route from navigation menus + * @default false + */ + excludeFromMenu?: boolean; + /** + * Display label for this route in navigation/menus + */ + label?: string; + /** + * Webpack chunk names to preload for this route (for SSR optimization) + * These should match the webpackChunkName comments in lazy imports + * @example ['signin', 'common-components'] + */ + preloadChunks?: string[]; +} +/** + * Collection of all routes in the application + * Key is the route identifier, value is the route configuration + */ +export type RoutesConfig = Record; +/** + * Module shape expected when loading routes dynamically + * Routes can be exported as ROUTES or as default export + */ +export interface RoutesModule { + ROUTES?: RoutesConfig; + default?: { + ROUTES?: RoutesConfig; + } | RoutesConfig; +} diff --git a/src/types/ShapeDetails.d.ts b/src/types/ShapeDetails.d.ts new file mode 100644 index 0000000..46ed181 --- /dev/null +++ b/src/types/ShapeDetails.d.ts @@ -0,0 +1,53 @@ +/** + * Shape metadata types for CMS UI. + * These types describe shape structure for frontend display — no graph-runtime dependency. + */ +export type PropertyDetails = { + id: string; + label: string; + path: { + id: string; + } | { + id: string; + }[]; + valueShape?: { + id: string; + }; + datatype?: { + id: string; + }; + description: string; + maxCount?: number; + minCount?: number; + nodeKind?: { + id: string; + }; + name?: string; + pattern?: string; + minLength?: number; + maxLength?: number; + minInclusive?: number; + maxInclusive?: number; + minExclusive?: number; + maxExclusive?: number; + inValues?: { + id: string; + label: string; + }[]; +}; +export type ShapeDetails = { + id: string; + label: string; + description: string; + targetClass?: { + id: string; + }; + type?: { + id: string; + }; + extends?: { + id: string; + }; + properties: PropertyDetails[]; + numInstances?: number; +}; diff --git a/src/utils/BackendProvider.d.ts b/src/utils/BackendProvider.d.ts new file mode 100644 index 0000000..2455ab6 --- /dev/null +++ b/src/utils/BackendProvider.d.ts @@ -0,0 +1,19 @@ +export declare class BackendProvider { + server: any; + lincdServer: any; + request: any; + response: any; + constructor(server: any, lincdServer: any); + /** + * Each request, all providers are given the opportunity to provide data for the request. + * For example, a provider that handles logins, may return data about the current user + * This data will then be available on the frontend right upon initialisation + */ + supplyDataForRequest(request: any, response: any, data: Record): Promise | void; + initRequest(request: any, response: any): Promise | void; + setupBeforeControllers(): void; + setupBeforeCatchAllControllers(): void; + setupAfterControllers(): void; + protected assignEnvPathToField(envKey: any, field: any): Promise; + protected callOtherProvider(provider: typeof BackendProvider): S; +} diff --git a/src/utils/Backup.d.ts b/src/utils/Backup.d.ts new file mode 100644 index 0000000..2315ece --- /dev/null +++ b/src/utils/Backup.d.ts @@ -0,0 +1,8 @@ +export declare class Backup { + static keepBackup(date: Date, now?: Date, keepConfig?: { + hourlyThreshold: number; + sixHoursThreshold: number; + weeklyThreshold: number; + monthlyThreshold: number; + }): boolean; +} diff --git a/src/utils/Frontend.d.ts b/src/utils/Frontend.d.ts new file mode 100644 index 0000000..a6cd2ac --- /dev/null +++ b/src/utils/Frontend.d.ts @@ -0,0 +1 @@ +export declare function initFrontend(): void; diff --git a/src/utils/ImageResize.d.ts b/src/utils/ImageResize.d.ts new file mode 100644 index 0000000..df3e7ec --- /dev/null +++ b/src/utils/ImageResize.d.ts @@ -0,0 +1 @@ +export declare function getResizedImagePath(fullImagePath: string, width?: number, height?: number): string; diff --git a/src/utils/JSONParser.d.ts b/src/utils/JSONParser.d.ts new file mode 100644 index 0000000..836e4bf --- /dev/null +++ b/src/utils/JSONParser.d.ts @@ -0,0 +1,18 @@ +export declare class JSONParser { + /** + * Parse a JSON string back into typed objects. + */ + static parse(json: string): T; + /** + * Convert a plain JS object back into typed objects. + * Recognizes markers (__s, __sc, __dt, __type) and reconstructs + * the corresponding Shape/collection instances. + */ + static parseObject(object: any): T; + private static parseInternal; + private static createShape; + private static createShapeClass; + private static createShapeSet; + private static createCoreSet; + private static createCoreMap; +} diff --git a/src/utils/JSONWriter.d.ts b/src/utils/JSONWriter.d.ts new file mode 100644 index 0000000..185ba63 --- /dev/null +++ b/src/utils/JSONWriter.d.ts @@ -0,0 +1,16 @@ +export declare class JSONWriter { + /** + * Convert any object to a JSON string. + * The result is meant to be consumed by JSONParser. + */ + static stringify(object: any): string; + /** + * Convert any object to a plain JS object suitable for JSON.stringify. + * Recursively converts Shape instances, Shape classes, Dates, and collections. + */ + static toJsObject(object: any): any; + private static convertShape; + private static convertShapeClass; + private static convertCoreSet; + private static convertCoreMap; +} diff --git a/src/utils/LincdServerProxy.d.ts b/src/utils/LincdServerProxy.d.ts new file mode 100644 index 0000000..f523414 --- /dev/null +++ b/src/utils/LincdServerProxy.d.ts @@ -0,0 +1,69 @@ +import { Shape } from '@_linked/core/shapes/Shape'; +export interface CallConfig { + method: string; + headers?: any; + setLoaded?: boolean; + overwriteData?: boolean; + /** + * If true, it will not use the local server but instead force a fetch call, which will then resolve again to the backend + * On a multicore set-up this may end up on a different worker + */ + forceFetch?: boolean; +} +export type ActionHandler = (event: { + preventDefault: () => void; +}) => void; +export declare class LincdServerProxy { + /** + * Use this key in a json response to trigger an action on the frontend. + */ + static RESPONSE_ACTION_KEY: string; + static actionHandlers: Map; + /** + * Is set by Server utility. Allows a LincdServer to bypass the proxy on the backend. + */ + localServer: any; + private rootUrl; + static defaultHeaders: { + Accept: string; + 'Content-Type': string; + }; + constructor(rootUrl: string | { + id?: string; + }); + static getFromURI(uri: string): LincdServerProxy; + get uri(): string; + /** + * Default headers to be sent with every request + * + * @param headers + */ + static addDefaultHeaders(headers: any): void; + static registerActionHandler(actionName: string, handler: ActionHandler): void; + /** + * Create a response action object that can be returned by a server call to trigger an action on the frontend. + * @param actionName + * @param args + */ + static createResponseAction(actionName: string, ...args: any[]): { + [x: string]: string | any[]; + args: any[]; + }; + /** + * Call a method on the server for this specific shape. + * See the documentation on `Providers` to learn more about implementing server side methods for shapes. + * @param shape + * @param method + * @param args + */ + call(packageName: string, method: string | CallConfig, ...args: any[]): Promise; + call(shape: Shape | typeof Shape, method: string | CallConfig, ...args: any[]): Promise; + callCustomShapeMethod(shape: typeof Shape | Shape, method: 'GET' | 'POST' | 'PUT' | 'UPDATE', methodName: any, body: any, headers?: any): Promise; + customPost(route: any, ...args: any[]): Promise; + private callBackendMethod; + private parseMethod; + private callShapeMethod; + private parseShape; + private fetchBackend; + handleResponseAction(action: any): boolean; +} diff --git a/src/utils/LinkedEmail.d.ts b/src/utils/LinkedEmail.d.ts new file mode 100644 index 0000000..7d1efe1 --- /dev/null +++ b/src/utils/LinkedEmail.d.ts @@ -0,0 +1,22 @@ +export interface IEmailProvider { + send(emailOptions: EmailOptions): Promise; +} +export interface EmailContact { + address: string; + name: string; +} +export interface EmailOptions { + bounce_address?: string; + from?: EmailContact; + to: { + email_address: EmailContact; + }[]; + subject: string; + htmlbody: string; +} +export declare class LinkedEmail { + private static provider; + static setDefaultProvider(provider: IEmailProvider): void; + static hasDefaultProvider(): boolean; + static send(emailOptions: EmailOptions): Promise; +} diff --git a/src/utils/LinkedLiveUpdates.d.ts b/src/utils/LinkedLiveUpdates.d.ts new file mode 100644 index 0000000..18a9cfa --- /dev/null +++ b/src/utils/LinkedLiveUpdates.d.ts @@ -0,0 +1,20 @@ +export interface UpdateMessage { + timestamp: number; + type: string; + data: any; +} +export declare const updates: UpdateMessage[]; +export declare class LinkedLiveUpdate { + static batchedUpdates: UpdateMessage[]; + /** + * To be used on the backend to send updates to the frontend. + * @param type + * @param data + */ + static send(type: string, data: any): void; + /** + * To be used on the frontend to get the latest updates from the backend. + * @param timestamp + */ + static getUpdatesSince(timestamp?: number, limit?: number): Promise; +} diff --git a/src/utils/RequestData.d.ts b/src/utils/RequestData.d.ts new file mode 100644 index 0000000..618313f --- /dev/null +++ b/src/utils/RequestData.d.ts @@ -0,0 +1,13 @@ +/** + * Get a certain key from the request data. + * Request data is data provided by the backend to the frontend + * @param key + */ +export declare function getRequestData(key?: string): any; +/** + * Sets the request data. Only to be used on frontend. + * For backend code use request.frontendData instead. + * @param key + * @param value + */ +export declare function setRequestData(key: any, value?: any): void; diff --git a/src/utils/Server.d.ts b/src/utils/Server.d.ts new file mode 100644 index 0000000..dab8b0a --- /dev/null +++ b/src/utils/Server.d.ts @@ -0,0 +1,47 @@ +import { Shape } from '@_linked/core/shapes/Shape'; +import { ActionHandler, CallConfig } from './LincdServerProxy.js'; +export { CallConfig } from './LincdServerProxy.js'; +/** + * This helper class makes API calls to a LincdServer backend easy by calling Server.call() + * This class is intended to be used on the frontend (and will also work on the backend for SSR) + */ +export declare class Server { + /** + * Only set this value from a node.js backend. This allows server calls to directly access a LincdServer without going through the proxy using fetch() + */ + static setLocalServer(server: any): void; + static getLocalServer(): any; + /** + * Set the default headers to be sent with every request + * @param headers + */ + static addDefaultHeaders(headers: any): void; + /** + * Register a handler for a response action. + * Response actions are triggered by the server by returning a json response with a key of `LincdServerProxy.RESPONSE_ACTION_KEY` and a value of the action name. + * They allow custom actions like redirects, alerts, and other UI changes to be triggered by the server. + * @param actionName + * @param handler + */ + static registerActionHandler(actionName: string, handler: ActionHandler): void; + /** + * Create a response action object that can be returned by a server call to trigger an action on the frontend. + * @param actionName + * @param args + */ + static createResponseAction(actionName: string, ...args: any[]): { + [x: string]: string | any[]; + args: any[]; + }; + /** + * Call a method on the server for this specific shape or package. + * See the documentation on `Providers` to learn more about implementing server side methods for shapes. + * @param shape + * @param method + * @param args + */ + static call(packageName: string, method: string | CallConfig, ...args: any[]): Promise; + static call(shape: Shape | typeof Shape, method: string | CallConfig, ...args: any[]): Promise; + static customPost(route: any, ...args: any[]): Promise; + static callCustomShapeMethod(shape: typeof Shape | Shape, httpMethod: 'GET' | 'POST' | 'PUT' | 'UPDATE', methodName: any, body: any, headers?: any): Promise; +} diff --git a/src/utils/ServerPaths.d.ts b/src/utils/ServerPaths.d.ts new file mode 100644 index 0000000..840bae4 --- /dev/null +++ b/src/utils/ServerPaths.d.ts @@ -0,0 +1,2 @@ +export declare const publicUploadPath = "/uploads"; +export declare const publishResizedImagePath = "/resized"; diff --git a/src/utils/ShapeIndex.d.ts b/src/utils/ShapeIndex.d.ts new file mode 100644 index 0000000..0d50899 --- /dev/null +++ b/src/utils/ShapeIndex.d.ts @@ -0,0 +1,9 @@ +/** + * Shape index — read-only access to the shape metadata index. + * The index itself is populated by syncShapes() in @_linked/server (backend-only). + * Frontend code uses getShapeIndex() and getShapeFromIndex() to read it. + */ +import type { ShapeDetails } from '../types/ShapeDetails.js'; +export declare const shapeIndex: Record; +export declare function getShapeFromIndex(uri: string): ShapeDetails; +export declare function getShapeIndex(): Record; diff --git a/src/utils/ShapeProvider.d.ts b/src/utils/ShapeProvider.d.ts new file mode 100644 index 0000000..e3e76c3 --- /dev/null +++ b/src/utils/ShapeProvider.d.ts @@ -0,0 +1,5 @@ +import { Shape } from '@_linked/core/shapes/Shape'; +import { BackendProvider } from './BackendProvider.js'; +export declare class ShapeProvider extends BackendProvider { + shape: typeof Shape; +} diff --git a/src/utils/Upload.d.ts b/src/utils/Upload.d.ts new file mode 100644 index 0000000..4e74977 --- /dev/null +++ b/src/utils/Upload.d.ts @@ -0,0 +1,33 @@ +import { File } from 'formidable'; +export declare const absoluteFileSystemDataPath: string; +export declare const absoluteFileSystemUploadPath: string; +export declare const relativeFileSystemDataPath: string; +export declare const relativeFileSystemUploadPath: string; +type UploadTarget = { + targetFileName: string; + targetFilePath: string; + publicURL: string; +}; +/** + * Get the target file name and path for a file upload + * @param fileName The original file name + * @param mimetype The mimetype of the file + * @param allowedExtensions An array of allowed file extensions + * @param addSuffix A suffix to add to the file name + */ +export declare function getUploadTarget(fileName: string, mimetype?: string, allowedExtensions?: string[], addSuffix?: string, accessURL?: string, preventDuplicates?: boolean): UploadTarget; +type UploadSingleFileFromFormData = { + file: File; + allowedExtensions?: string[]; + processDataFn?: (data: any) => any; + addSuffix?: string; +}; +export declare function uploadSingleFileFromFormData({ file, allowedExtensions, processDataFn, addSuffix, }: UploadSingleFileFromFormData): Promise; +type UploadSingleFileFromBufferType = { + buffer: Buffer; + fileName: string; + allowedExtensions?: string[]; + addSuffix?: string; +}; +export declare function uploadSingleFileFromBuffer({ buffer, fileName, allowedExtensions, addSuffix, }: UploadSingleFileFromBufferType): Promise; +export {};