_A blue tiger with a laptop under his shoulder walks to work, greeting a_
_floating robotic datacentre technician on his way to his office._

At Tigris, we do object storage. However, in order to use Tigris in your
JavaScript or TypeScript projects, you normally have to import a library from
AWS. We want you to import Tigris to use Tigris, so we made the
[Tigris Storage SDK](/content/docs/sdks/tigris/index.html) to make
interactions with object storage simpler. Here’s how you use it compared to the
AWS S3 SDK:

Tigris | AWS
------- | ---- 
Tigris Storage SDK | AWS S3 SDK

```javascript
import { put } from "@tigrisdata/storage";

await put("object.txt", "Hello, World!");
```

```javascript
import {

S3Client,

PutObjectCommand

} from "@aws-sdk/client-s3";

const s3Client = new S3Client({

region: "us-east-1",

});

const data = await s3Client.send(

new PutObjectCommand({

Bucket: "your-bucket-name",

Key: "object.txt",

Body: "hello world",

ContentType: "text/plain",

})
);
```

You can get started with the Tigris Storage SDK by installing the NPM package
[`@tigrisdata/storage`](https://www.npmjs.com/package/@tigrisdata/storage):

- npm
- Yarn

```bash
npm install --save @tigrisdata/storage
```

```bash
yarn add @tigrisdata/storage
```

From there, [create a bucket](https://console.storage.dev/createbucket?pid=019f72ce-a67e-7978-b5a2-90a9a287f538&sid=019f72ce-a685-79ae-8825-cfef98e9c5b1),
[create an Editor keypair for that bucket](https://console.storage.dev/createaccesskey?pid=019f72ce-a67e-7978-b5a2-90a9a287f538&sid=019f72ce-a685-79ae-8825-cfef98e9c5b1),
and add the following to your `.env` file (or to the project’s environment in
your runtime of choice):

```sh
TIGRIS_STORAGE_ACCESS_KEY_ID=tid_access_key_id

TIGRIS_STORAGE_SECRET_ACCESS_KEY=tsec_secret_access_key

TIGRIS_STORAGE_BUCKET=mybucket
```

That’s it!

## Why make a storage SDK?  
Object storage is a very simple concept that ended up being complicated in
practice. When we designed the Tigris Storage SDK, we wanted to pare it down to
the bare essentials. If you need to put an object into Tigris, you use the `put`
function. This automatically figures out where to store things, what credentials
to use, and all the other minutæ you have to deal with. You just put, get, list,
and delete objects.

This adds up to give you the ability to glance at the code and have a good idea
of what is actually going on. Compare these two code snippets:

Tigris | AWS
------- | ---- 
Tigris Storage SDK | AWS S3 SDK

```javascript
import { list } from "@tigrisdata/storage";

const { data, error } =

await list({ limit: 100 });

if (error !== undefined) {

console.error("Error listing files:", error);
}

data.forEach(({ name, size }) => {

console.log(`${name}: ${size} bytes`);
});
```

```javascript
import {

S3Client,

ListObjectsV2Command

} from "@aws-sdk/client-s3";

const s3Client = new S3Client({

region: "us-east-1"
});

const command = new ListObjectsV2Command({

Bucket: "my-bucket",

MaxKeys: 100,
});

const response = await s3Client.send(command);

response.Contents.forEach((item) => {

console.log(`${item.Key}: ${item.Size} bytes`);
});
```

Which one would you rather read in your codebase? The cognitive complexity
reduction in the Tigris Storage SDK is subtle but significant. By default, the
Tigris Storage SDK loads all of its configuration
[from the environment](https://12factor.net/config) like any good twelve-factor
app should:

| Tigris Storage SDK | AWS |
| ------------------ | --- |
| `TIGRIS_STORAGE_ACCESS_KEY_ID` | `AWS_ACCESS_KEY_ID` |
| `TIGRIS_STORAGE_SECRET_ACCESS_KEY` | `AWS_SECRET_ACCESS_KEY` |
| `TIGRIS_STORAGE_BUCKET` | No equivalent, you must set it manually per call |

However, if you need to `put` things into a different bucket, you can do that
with the `config` argument:

```javascript
import { put } from "@tigrisdata/storage";

const { data, error } = put(`avatars/${user.id}`, avatarBlob, {

addRandomSuffix: true,

config: {

bucket: "contoso-user-data",

},
});

if (error !== undefined) {

throw error; // or whatever else you do in your project
}

console.log(`Data uploaded to tigris as ${data.path}`);

console.log(`URL: ${data.url}`);
```

This will put a user’s avatar data into the Tigris bucket `contoso-user-data`
and suffix the name with the time (in Unix milliseconds) and random data. You
can also
[set the access key id, secret access key, and API endpoint on a per-bucket basis](/content/docs/sdks/tigris/using-sdk/#authentication/index.html).

You may have noticed something interesting in that last example:

```javascript
const { data, error } = put(`avatars/${user.id}`, avatarBlob);

if (error !== undefined) {

throw error; // or whatever else you do in your project
}

// use data
```

When possible, we return errors as _values_ instead of throwing exceptions up
the stack. This pattern allows you to handle errors inline to your code so they
aren’t surprises when they come up in practice. This adds up to reduce the
cognitive complexity of your code so you can go back to shipping your multicloud
agentic SaaS of your dreams!

This also means you don’t have to instantiate classes or ferry around a client
global when you want to do basic operations:

Tigris | AWS
------- | ---- 
Tigris Storage SDK | AWS S3 SDK

```javascript
import { get } from "@tigrisdata/storage";

const { data, error } = get("object.txt", "string");

if (error !== undefined) {

// or whatever else you do in your project

throw error;
}

console.log(data);
```

```javascript
import {

S3Client,

GetObjectCommand

} from "@aws-sdk/client-s3";

const s3Client = new S3Client({

region: "us-east-1"
});

const command = new GetObjectCommand({

Bucket: "my-bucket",

Key: "object.txt",
});

const response = await s3Client.send(command);

const data = response.Body.transformToString("utf-8");

console.log(data);
```

Need to upload a large file? The multipart upload feature is there for you!

```javascript
const videoStream = new ReadableStream({

start(controller) {

controller.enqueue(new TextEncoder().encode("Hello, World!"));

controller.close();

},
});

const { data, error } = await put("videos/large-video.mp4", videoStream, {

multipart: true,

onUploadProgress: ({ percentage }) => {

console.log(`Upload progress: ${percentage}%`);
  },
});

if (error !== undefined) {

throw error; // or whatever else you do in your project
}

console.log(data);
```

## Client uploads  
Tigris
[does not charge egress fees](/content/pricing/#zero-egress-fees/index.html),
but the provider you run your app on likely does. This means that uploading data
to Tigris from your app can run up a cost per gigabyte. To work around this,
we’ve created the
[client upload pattern](/content/docs/sdks/tigris/client-uploads/index.html).
This makes your app return a
[presigned `PUT` URL](/content/docs/objects/presigned/index.html) to the
client and then the client uploads the data directly to Tigris, sidestepping the
entire part where your app needs to stream data from the client and then upload
it to Tigris.

In order to implement this, you need to do the following:

- Expose an upload endpoint that creates pre-signed URLs, for example:
`/api/upload`
- Call the `upload` function from `@tigrisdata/storage/client` module like this:

```javascript
import { upload } from "@tigrisdata/storage/client";

const { data, error } = await upload(file.name), file, {

url: "/api/upload", // or whatever endpoint you use

access: "private", // or public

onUploadProgress: ({ loaded, total, percentage }) => {

console.log({ loaded, total, percentage });
  },
};

if (error !== undefined) {

throw error; // or whatever you do normally
}

console.log(data);
```

And then your data is uploaded by the client instead of having to pipe it
through to the server! Make sure to secure this API endpoint appropriately, add
rate limits, and all the other protections you should do for production
services. Note that you may need to combine this with
[setting CORS for your bucket](/content/docs/buckets/cors/index.html)
and
[using custom branded presigned URLs](/content/docs/objects/presigned/#presigned-url-with-custom-domain/index.html)
for the best effect.

## Conclusion  
If you want to try the Tigris Storage SDK, install it from npm:

- npm
- Yarn

```bash
npm install --save @tigrisdata/storage
```

```bash
yarn add @tigrisdata/storage
```

If you want to learn more about the Tigris Storage SDK, check out these links
for more information:

Globally performant object storage

Tigris is dedicated to making sure that your experience with object storage is the best it can possibly be, and then we go the extra mile to make it even better.
