Skip to content

docs: add example repository and update documentation #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 27, 2025
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 .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Environment variables
.env
.env.*
!.env.example
node_modules
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ This repository contains a set of packages for interacting with the [HackMD API]

See [README](./nodejs)

## Examples

To help you get started quickly, we provide comprehensive usage examples in the `examples/` directory:

### Node.js Example

The `examples/nodejs/` directory contains a complete example project demonstrating:

- User information retrieval
- Note creation and management
- ETag support for caching
- Content updates
- Error handling with retry logic
- Environment variable configuration

To run the Node.js example:

1. Navigate to the example directory: `cd examples/nodejs`
2. Follow the setup instructions in [examples/nodejs/README.md](./examples/nodejs/README.md)
3. Set your HackMD access token
4. Run `npm start`

The example includes detailed comments and demonstrates best practices for using the HackMD API client.

## LICENSE

MIT
1 change: 1 addition & 0 deletions examples/nodejs/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
HACKMD_ACCESS_TOKEN=YOUR_ACCESS_TOKEN
63 changes: 63 additions & 0 deletions examples/nodejs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# HackMD API Client Example

This is an example project demonstrating the usage of the HackMD API client.

## Setup

1. First, build the HackMD API package:
```bash
cd ../../nodejs
npm install
npm run build
cd ../examples/nodejs
```

2. Install the example dependencies:
```bash
npm install
```

3. Set up your HackMD access token using one of these methods:

a. Set it as an environment variable:
```bash
# For Unix/Linux/macOS
export HACKMD_ACCESS_TOKEN=your_access_token_here

# For Windows PowerShell
$env:HACKMD_ACCESS_TOKEN="your_access_token_here"
```

b. Or create a `.env` file in the project root (not tracked by git):
```
HACKMD_ACCESS_TOKEN=your_access_token_here
```

You can get your access token from [HackMD API documentation](https://hackmd.io/@hackmd-api/developer-portal).

## Running the Example

To run the example:

```bash
npm start
```

## What's Demonstrated

The example demonstrates several features of the HackMD API client:

1. Getting user information
2. Creating a new note
3. Using ETag support for caching
4. Updating note content
5. Getting raw response data
6. Deleting notes

## Features Shown

- Retry configuration with exponential backoff
- ETag support for caching
- Response data unwrapping
- Error handling
- Environment variable configuration
77 changes: 77 additions & 0 deletions examples/nodejs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import HackMDAPI from '@hackmd/api';
import dotenv from 'dotenv';

// Load environment variables
dotenv.config();

// Check for required environment variable
if (!process.env.HACKMD_ACCESS_TOKEN) {
console.error('Error: HACKMD_ACCESS_TOKEN environment variable is not set.');
console.error('Please set your HackMD access token using one of these methods:');
console.error('1. Create a .env file with HACKMD_ACCESS_TOKEN=your_token_here');
console.error('2. Set the environment variable directly: export HACKMD_ACCESS_TOKEN=your_token_here');
process.exit(1);
}

// Create API client with retry configuration
const client = new HackMDAPI(process.env.HACKMD_ACCESS_TOKEN, 'https://api.hackmd.io/v1', {
retryConfig: {
maxRetries: 3,
baseDelay: 100
}
});

async function main() {
try {
// Example 1: Get user information
console.log('Getting user information...');
const me = await client.getMe();
console.log('User email:', me.email);
console.log('User name:', me.name);

// Example 2: Create a new note
console.log('\nCreating a new note...');
const newNote = await client.createNote({
title: 'Test Note',
content: '# Hello from HackMD API\n\nThis is a test note created using the API client.',
readPermission: 'guest',
writePermission: 'owner'
});
console.log('Created note ID:', newNote.id);
console.log('Note URL:', newNote.publishLink);

// Example 3: Get note with ETag support
console.log('\nGetting note with ETag support...');
const note = await client.getNote(newNote.id);
console.log('Note content:', note.content);

// Second request with ETag
const updatedNote = await client.getNote(newNote.id, { etag: note.etag });
console.log('Note status:', updatedNote.status);

// Example 4: Update note content
console.log('\nUpdating note content...');
const updatedContent = await client.updateNoteContent(newNote.id, '# Updated Content\n\nThis note has been updated!');
console.log('Updated note content:', updatedContent.content);

// Example 5: Get raw response (unwrapData: false)
console.log('\nGetting raw response...');
const rawResponse = await client.getNote(newNote.id, { unwrapData: false });
console.log('Response headers:', rawResponse.headers);
console.log('Response status:', rawResponse.status);

// Example 6: Delete the test note
console.log('\nCleaning up - deleting test note...');
await client.deleteNote(newNote.id);
console.log('Note deleted successfully');

} catch (error) {
console.error('Error:', error.message);
if (error.response) {
console.error('Response status:', error.response.status);
console.error('Response data:', error.response.data);
}
}
}

main();
57 changes: 57 additions & 0 deletions examples/nodejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions examples/nodejs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "hackmd-api-example",
"version": "1.0.0",
"description": "Example usage of HackMD API client",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@hackmd/api": "file:../../nodejs",
"dotenv": "^16.4.5"
}
}
2 changes: 1 addition & 1 deletion nodejs/.eslintrc.js → nodejs/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const config = {
]
},
"ignorePatterns": [
".eslintrc.js"
".eslintrc.cjs"
],
}

Expand Down
85 changes: 85 additions & 0 deletions nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,101 @@ npm install @hackmd/api --save

## Example

### ES Modules (ESM)

```javascript
// Default import
import HackMDAPI from '@hackmd/api'

// Or named import
import { API } from '@hackmd/api'

const client = new HackMDAPI('YOUR_ACCESS_TOKEN' /* required */, 'https://api.hackmd.io/v1' /* optional */)

client.getMe().then(me => {
console.log(me.email)
})
```

### CommonJS

```javascript
// Default import
const HackMDAPI = require('@hackmd/api').default

// Or named import
const { API } = require('@hackmd/api')

const client = new HackMDAPI('YOUR_ACCESS_TOKEN', 'https://api.hackmd.io/v1')

client.getMe().then(me => {
console.log(me.email)
})
```

### Legacy Import Support

For backward compatibility, the package also supports legacy import paths:

```javascript
// ESM
import HackMDAPI from '@hackmd/api/dist'
import { API } from '@hackmd/api/dist'

// CommonJS
const HackMDAPI = require('@hackmd/api/dist').default
const { API } = require('@hackmd/api/dist')

// Direct file imports
import { API } from '@hackmd/api/dist/index.js'
```

## Advanced Features

### Retry Configuration

The client supports automatic retry for failed requests with exponential backoff. You can configure retry behavior when creating the client:

```javascript
const client = new HackMDAPI('YOUR_ACCESS_TOKEN', 'https://api.hackmd.io/v1', {
retryConfig: {
maxRetries: 3, // Maximum number of retry attempts
baseDelay: 100 // Base delay in milliseconds for exponential backoff
}
})
```

The client will automatically retry requests that fail with:
- 5xx server errors
- 429 Too Many Requests errors
- Network errors

### Response Data Handling

By default, the client automatically unwraps the response data from the Axios response object. You can control this behavior using the `unwrapData` option:

```javascript
// Get raw Axios response (includes headers, status, etc.)
const response = await client.getMe({ unwrapData: false })

// Get only the data (default behavior)
const data = await client.getMe({ unwrapData: true })
```

### ETag Support

The client supports ETag-based caching for note retrieval. You can pass an ETag to check if the content has changed:

```javascript
// First request
const note = await client.getNote('note-id')
const etag = note.etag

// Subsequent request with ETag
const updatedNote = await client.getNote('note-id', { etag })
// If the note hasn't changed, the response will have status 304
```

## API

See the [code](./src/index.ts) and [typings](./src/type.ts). The API client is written in TypeScript, so you can get auto-completion and type checking in any TypeScript Language Server powered editor or IDE.
Expand Down
Loading