Skip to content

Commit d82ebc3

Browse files
authored
Merge pull request #4 from sqlitecloud/feat/object-storage-interface
added object storage wrapper to repo
2 parents 34a1df4 + cc75085 commit d82ebc3

File tree

9 files changed

+479
-0
lines changed

9 files changed

+479
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.env
3+
.DS_Store

object-storage-interface/README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Object Storage Interface
2+
3+
This project implements a TypeScript interface for object storage, similar to [AWS SDK for JavaScript v3 s3 actions](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_s3_code_examples.html). It uses [SQLite Cloud](https://docs.sqlitecloud.io/) as the database for storing and retrieving objects.
4+
5+
### Features
6+
7+
- **Object Storage**: Store, retrieve, list, and delete objects in named buckets.
8+
9+
### Prerequisites
10+
11+
- Node.js
12+
- TypeScript
13+
- [SQLite Cloud account](https://sqlitecloud.io/register) and connection string
14+
15+
### Installation
16+
17+
1. Clone the repository
18+
19+
```bash
20+
git clone <repository-url>
21+
cd <repository-directory>
22+
```
23+
24+
2. Install dependencies
25+
26+
```bash
27+
npm install
28+
```
29+
30+
3. Create a `.env` file in the root directory and add your SQLite Cloud connection string
31+
32+
Grab a connection string by clicking on a node in your dashboard. Make sure to add the database name to the connecting string you get. The host is already included in your connection string.
33+
34+
```bash
35+
DB_CONNECTION_STRING="sqlitecloud://{HOST}.sqlite.cloud:8860/{DATABASE_NAME}?apikey=#######"
36+
```
37+
38+
### Usage
39+
40+
The main class `ObjectClient` provides an interface similar to AWS S3.
41+
42+
The `ObjectClient` class has an init method and a send method. The init method creates a table to store objects and their metadata, including a bucket attribute for categorization. The send method takes in a command object and calls the command’s “execute” method.
43+
44+
The project uses a command pattern, encapsulating each operation (like getting, putting, listing, or deleting an object) in a class. Each command class implements an execute method that performs the action using the provided database instance.
45+
46+
#### Available Commands
47+
48+
- `PutObjectCommand`: Upload an object to a bucket
49+
- `GetObjectCommand`: Retrieve an object from a bucket
50+
- `DeleteObjectCommand`: Delete an object from a bucket
51+
- `ListBucketsCommand`: List all buckets
52+
- `ListObjectsCommand`: List objects in a bucket
53+
- `ListObjectsByDateCommand`: List objects in a bucket within a date range
54+
55+
The `ListObjectsByDateCommand` class, allows users to query objects in a bucket by date range. This class accepts either a timestamp or a date in the format YYYY-MM-DD as an argument.
56+
57+
#### Response
58+
59+
All commands return a CommandResponse object with the following structure:
60+
61+
```typescript
62+
{
63+
error: any | null,
64+
result: any | null,
65+
message: string
66+
}
67+
```
68+
69+
#### Example Usage
70+
71+
Below is an example of how to use the Object Storage Wrapper:
72+
73+
```typescript
74+
import { ObjectClient, PutObjectCommand, GetObjectCommand } from "./main";
75+
76+
const main = async () => {
77+
const objectStorage = new ObjectClient(process.env.DB_CONNECTION_STRING!);
78+
79+
// Put an object
80+
const putObject = new PutObjectCommand({
81+
bucket: "documents",
82+
key: "example.pdf",
83+
body: "./path/to/example.pdf",
84+
});
85+
const putResponse = await objectStorage.send(putObject);
86+
87+
// Get an object
88+
const getObject = new GetObjectCommand({
89+
bucket: "documents",
90+
key: "example.pdf",
91+
});
92+
const getResponse = await objectStorage.send(getObject);
93+
};
94+
95+
main();
96+
```
97+
98+
### Directory Structure
99+
100+
- `initializeObjectsTable.ts`: Contains the logic to initialize the database table for storing objects.
101+
- `main.ts`: Main entry point for the example usage.
102+
- `types.d.ts`: Defines TypeScript types for various requests and responses.
103+
- `utils.ts`: Utility functions, such as field validation.
844 KB
Binary file not shown.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Database } from "@sqlitecloud/drivers";
2+
3+
// CREATE OBJECTS TABLE
4+
export const initializeObjectsTable = (db: Database) => {
5+
const createTableStatement = `
6+
CREATE TABLE IF NOT EXISTS objects (
7+
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
8+
bucket TEXT NOT NULL,
9+
key TEXT NOT NULL,
10+
file BLOB NOT NULL,
11+
created_at TEXT NOT NULL,
12+
modified_at TEXT NOT NULL,
13+
UNIQUE (bucket, key)
14+
);`;
15+
const createIndexStatement = `
16+
CREATE INDEX IF NOT EXISTS idx_objects_bucket_key ON objects (bucket, key);
17+
CREATE INDEX IF NOT EXISTS idx_objects_key ON objects (key);
18+
`;
19+
try {
20+
db.run(createTableStatement);
21+
console.log("Successfully created table or table already exists");
22+
db.run(createIndexStatement);
23+
console.log("Successfully created index or index already");
24+
return { error: null, message: "Successfully created table and index" };
25+
} catch (error) {
26+
return { error, message: "Error creating table and index" };
27+
}
28+
};

0 commit comments

Comments
 (0)