dimah-s3v1.5.11
@dimah-s3/core

@dimah-s3/core

Shared protocol routes, isomorphic client, error types, and pure helpers.

@dimah-s3/core is the protocol source of truth shared by @dimah-s3/server and @dimah-s3/react.

What lives here

  • S3_API_ROUTES / S3_API_BASE_PATH — canonical route paths
  • createS3Client — browser/isomorphic client implementing S3Api (+ client plugins). Exposes $ERROR_CODES, $fetch, $Infer. baseURL wins over basePath. Upload and download expiresIn default to 600 seconds (S3_DEFAULT_EXPIRES_IN) on the server.
  • APIError — error class with status and body. Serialized as JSON { message, code?, params? }. Use APIError.from(status, S3_ERROR_CODES.FORBIDDEN) or isAPIError. Catalog: Errors.
  • s3FetchErrorSchema — Zod schema for that JSON error body
  • Client plugin helpers — defineClientPlugin, createS3Fetch, pluginPath
  • Pure file helpers — validateFile, formatFileSize, buildContentDisposition, …

The browser client (createS3Client) uses nested calls (api.download({ route, key }), api.multipart.init). The server s3.api uses query-based handlers (s3.api.download({ query })) and the same nested aliases (s3.api.multipart.init). The protocol uses these paths under basePath (default /api/s3):

ConstantMethodPath
uploadPOST/presign/upload
uploadConfirmPOST/presign/upload/confirm
downloadGET/presign/download
fileGET/file
catalogGET/routes
deleteDELETE/delete
deleteBatchPOST/delete/batch
multipartInitPOST/presign/multipart/init
multipartPartPOST/presign/multipart/part
multipartListPartsGET/presign/multipart/parts
multipartCompletePOST/presign/multipart/complete
multipartAbortPOST/presign/multipart/abort

file is the server-side proxy target returned by download when its mode is "proxy"; it is not a separate S3Api client method.

Quick start

import { createS3Client } from "@dimah-s3/core";
import { dbClient } from "@dimah-s3/db/client";

export const api = createS3Client({
  basePath: "/api/s3",
  credentials: "include", 
  plugins: [dbClient()], 
});

await api.upload({
  route: "avatar",
  fileName: "avatar.png",
  contentType: "image/png",
  fileSize: 1024,
});
await api.db.listObjects({ limit: 20, offset: 0 });

For React apps prefer createS3Client from @dimah-s3/react — same options, plus a bound Provider / typed useApi on the client object.

Client plugins

import { defineClientPlugin, pluginPath } from "@dimah-s3/core";

export function myClient() {
  return defineClientPlugin({
    id: "my",
    getActions: ($fetch) => ({
      ping: () => $fetch(pluginPath("my", "ping"), { method: "GET" }),
    }),
  });
}

Paths must match the server plugin endpoint (e.g. createS3Endpoint("/my/ping", …)).

Validation

validateFile returns { code, message, params? } (or null). On the client, useFormatValidateFileError maps code to a UI string.

On this page