Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/puny-ravens-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@smooai/file': patch
---

Adding fully tested File library ready for publishing.
2 changes: 1 addition & 1 deletion .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: 22

- uses: pnpm/action-setup@v2
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.13.0
v22.14.0
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @smooai/library-template
# @smooai/file

## 1.0.2

Expand Down
206 changes: 178 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,52 +35,202 @@ SmooAI is a platform for building and deploying AI-powered apps.

Learn more on [smoo.ai](https://smoo.ai)

## About @smooai/library-template
## About @smooai/file

A template repository for creating new SmooAI libraries with standardized tooling, configuration, and best practices.
A powerful file handling library for Node.js that provides a unified interface for working with files from local filesystem, S3, URLs, and more. Built with streaming in mind, it handles file bytes lazily where possible to minimize memory usage and improve performance.

![GitHub License](https://img.shields.io/github/license/SmooAI/library-template?style=for-the-badge)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/SmooAI/library-template/release.yml?style=for-the-badge)
![GitHub Repo stars](https://img.shields.io/github/stars/SmooAI/library-template?style=for-the-badge)
![NPM Version](https://img.shields.io/npm/v/%40smooai%2Ffile?style=for-the-badge)
![NPM Downloads](https://img.shields.io/npm/dw/%40smooai%2Ffile?style=for-the-badge)
![NPM Last Update](https://img.shields.io/npm/last-update/%40smooai%2Ffile?style=for-the-badge)

![GitHub License](https://img.shields.io/github/license/SmooAI/file?style=for-the-badge)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/SmooAI/file/release.yml?style=for-the-badge)
![GitHub Repo stars](https://img.shields.io/github/stars/SmooAI/file?style=for-the-badge)

### Install

```sh
pnpm add @smooai/file
```

### Key Features

- 📦 Preconfigured development environment with TypeScript, ESLint, and Prettier
- 🧪 Testing setup with Vitest
- 🔄 Changesets for version management
- 📚 Integration with SmooAI core utilities
#### 🚀 Stream-First Design

### Dependencies
- Lazy loading of file contents
- Memory-efficient processing
- Automatic stream handling
- Support for both Node.js and Web streams

This template comes pre-configured with essential SmooAI packages:
#### 📦 Multiple File Sources

#### @smooai/logger
- **Local Filesystem**

A structured logging utility for SmooAI applications that provides:
- Read and write operations
- File system checks
- Metadata extraction

- Standardized log formatting
- Log level management
- Integration with SmooAI's logging infrastructure
- **URLs**

#### @smooai/utils
- Automatic download
- Stream-based transfer
- Header metadata extraction

Common utility functions and helpers used across SmooAI applications.
- **S3 Objects**

### Development Setup
- Direct S3 integration (download and upload)
- Stream-based transfer
- Header metadata extraction
- Signed URL generation

1. Clone the repository
2. Install dependencies:
- **FormData**
- Ease of use for Multipart FormData upload

```sh
pnpm install
#### 🔍 Intelligent File Type Detection

Powered by [file-type](https://github.com/sindresorhus/file-type), providing:

- Magic number detection
- MIME type inference
- File extension detection
- Support for 100+ file types

#### 📝 Rich Metadata

- File name and extension
- MIME type detection
- File size
- Last modified date
- Creation date
- File hash/checksum
- URL and path information
- Source type

### Examples

- [Basic Usage](#basic-usage)
- [Streaming Operations](#streaming-operations)
- [S3 Integration](#s3-integration)
- [File Type Detection](#file-type-detection)
- [FormData Support](#formdata-support)

#### Basic Usage <a name="basic-usage"></a>

```typescript
import File from '@smooai/file';

// Create a file from a local path
const file = await File.createFromFile('path/to/file.txt');

// Read file contents (streams automatically)
const content = await file.readFileString();
console.log(content);

// Get file metadata
console.log(file.metadata);
// {
// name: 'file.txt',
// mimeType: 'text/plain',
// size: 1234,
// extension: 'txt',
// path: 'path/to/file.txt',
// lastModified: Date,
// createdAt: Date
// }
```

<p align="right">(<a href="#examples">back to examples</a>)</p>

#### Streaming Operations <a name="streaming-operations"></a>

```typescript
import File from '@smooai/file';

// Create a file from a URL (streams automatically)
const file = await File.createFromUrl('https://example.com/large-file.zip');

// Pipe to a destination (streams without loading entire file)
await file.pipeTo(someWritableStream);

// Read as bytes (streams in chunks)
const bytes = await file.readFileBytes();

// Save to filesystem (streams directly)
const { original, newFile } = await file.saveToFile('downloads/file.zip');
```

### Available Scripts
<p align="right">(<a href="#examples">back to examples</a>)</p>

#### S3 Integration <a name="s3-integration"></a>

```typescript
import File from '@smooai/file';

// Create from S3 (streams automatically)
const file = await File.createFromS3('my-bucket', 'path/to/file.jpg');

// Upload to S3 (streams directly)
await file.uploadToS3('my-bucket', 'remote/file.jpg');

// Save to S3 (creates new file instance)
const { original, newFile } = await file.saveToS3('my-bucket', 'remote/file.jpg');

// Move to S3 (deletes local file if source was local)
const s3File = await file.moveToS3('my-bucket', 'remote/file.jpg');

// Generate signed URL
const signedUrl = await s3File.getSignedUrl(3600); // URL expires in 1 hour
```

<p align="right">(<a href="#examples">back to examples</a>)</p>

#### File Type Detection <a name="file-type-detection"></a>

```typescript
import File from '@smooai/file';

const file = await File.createFromFile('document.xml');

// Get file type information (detected via magic numbers)
console.log(file.mimeType); // 'application/xml'
console.log(file.extension); // 'xml'

// File type is automatically detected from:
// - Magic numbers (via file-type)
// - MIME type headers
// - File extension
// - Custom detectors
```

<p align="right">(<a href="#examples">back to examples</a>)</p>

#### FormData Support <a name="formdata-support"></a>

```typescript
import File from '@smooai/file';

const file = await File.createFromFile('document.pdf');

// Convert to FormData for uploads
const formData = await file.toFormData('document');

// Use with fetch or other HTTP clients
await fetch('https://api.example.com/upload', {
method: 'POST',
body: formData,
});
```

<p align="right">(<a href="#examples">back to examples</a>)</p>

### Built With

- `pnpm test` - Run tests using Vitest
- `pnpm build` - Build the library using tsup
- `pnpm lint` - Run ESLint
- `pnpm format` - Format code with Prettier
- TypeScript
- Node.js File System API
- AWS SDK v3
- [file-type](https://github.com/sindresorhus/file-type) for magic number-based MIME type detection
- [@smooai/fetch](https://github.com/SmooAI/fetch) for URL downloads
- [@smooai/logger](https://github.com/SmooAI/logger) for structured logging

## Contributing

Expand Down
69 changes: 52 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
{
"name": "@smooai/library-template",
"name": "@smooai/file",
"version": "1.0.2",
"private": true,
"description": "SmooAI Library Template",
"homepage": "https://github.com/SmooAI/library-template#readme",
"description": "A powerful file handling library for Node.js that provides a unified interface for working with files from local filesystem, S3, URLs, and more. Built with streaming in mind, it handles file bytes lazily where possible to minimize memory usage and improve performance.",
"homepage": "https://github.com/SmooAI/file#readme",
"bugs": {
"url": "https://github.com/SmooAI/library-template/issues"
"url": "https://github.com/SmooAI/file/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/SmooAI/library-template.git"
"url": "https://github.com/SmooAI/file.git"
},
"license": "MIT",
"author": {
"name": "SmooAI",
"email": "brent@smooai.com",
"url": "https://smooai.com"
},
"exports": {},
"main": "index.js",
"exports": {
"./File": {
"types": "./dist/File.d.ts",
"import": "./dist/File.mjs",
"require": "./dist/File.js",
"default": "./dist/File.js"
},
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"build": "pnpm create-entry-points -i \"src/**/*.ts\" && pnpm tsup",
"check-all": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
Expand All @@ -27,30 +45,47 @@
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"prepare": "husky",
"test": "vitest run --passWithNoTests",
"test": "vitest run",
"test:integration": "vitest run File.integration.spec",
"typecheck": "tsc --noEmit --skipLibCheck",
"watch": "tsup --watch"
},
"dependencies": {
"@smooai/logger": "^1.0.14",
"@smooai/utils": "^1.0.12"
"@aws-sdk/client-s3": "^3.777.0",
"@aws-sdk/s3-request-presigner": "^3.777.0",
"@file-type/xml": "^0.4.1",
"@smooai/fetch": "^1.0.7",
"@smooai/logger": "^1.0.19",
"@smooai/utils": "^1.0.18",
"content-disposition": "^0.5.4",
"file-type": "^20.4.1",
"formdata-node": "^6.0.3",
"mime-types": "^2.1.35",
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@changesets/cli": "^2.28.1",
"@smooai/config-eslint": "^1.0.9",
"@smooai/config-typescript": "^1.0.13",
"@types/node": "^20.13.0",
"@smooai/config-eslint": "^1.0.12",
"@smooai/config-typescript": "^1.0.16",
"@types/content-disposition": "^0.5.8",
"@types/mime-types": "^2.1.4",
"@types/node": "^22.13.10",
"@vercel/style-guide": "^6.0.0",
"eslint": "^9.21.0",
"husky": "^9.1.7",
"lint-staged": "^15.4.3",
"msw": "^2.7.3",
"prettier": "^3.5.3",
"prettier-plugin-packagejson": "^2.5.10",
"tsup": "^8.4.0",
"vite": "^5.4.14",
"vite-node": "^3.0.8",
"vite": "^6.2.3",
"vite-node": "^3.0.9",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.0.7"
"vitest": "^3.0.9",
"vitest-tsconfig-paths": "^3.4.1"
},
"packageManager": "pnpm@10.6.1+sha512.40ee09af407fa9fbb5fbfb8e1cb40fbb74c0af0c3e10e9224d7b53c7658528615b2c92450e74cfad91e3a2dcafe3ce4050d80bda71d757756d2ce2b66213e9a3"
"packageManager": "pnpm@10.6.1+sha512.40ee09af407fa9fbb5fbfb8e1cb40fbb74c0af0c3e10e9224d7b53c7658528615b2c92450e74cfad91e3a2dcafe3ce4050d80bda71d757756d2ce2b66213e9a3",
"publishConfig": {
"access": "public"
}
}
Loading