Skip to content

Commit ed9db81

Browse files
authored
Merge pull request #36 from hackmdio/docs/update-readme
docs: add example repository and update documentation
2 parents 11c1cdf + 7afaa6b commit ed9db81

File tree

14 files changed

+1942
-552
lines changed

14 files changed

+1942
-552
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Environment variables
2+
.env
3+
.env.*
4+
!.env.example
5+
node_modules

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ This repository contains a set of packages for interacting with the [HackMD API]
66

77
See [README](./nodejs)
88

9+
## Examples
10+
11+
To help you get started quickly, we provide comprehensive usage examples in the `examples/` directory:
12+
13+
### Node.js Example
14+
15+
The `examples/nodejs/` directory contains a complete example project demonstrating:
16+
17+
- User information retrieval
18+
- Note creation and management
19+
- ETag support for caching
20+
- Content updates
21+
- Error handling with retry logic
22+
- Environment variable configuration
23+
24+
To run the Node.js example:
25+
26+
1. Navigate to the example directory: `cd examples/nodejs`
27+
2. Follow the setup instructions in [examples/nodejs/README.md](./examples/nodejs/README.md)
28+
3. Set your HackMD access token
29+
4. Run `npm start`
30+
31+
The example includes detailed comments and demonstrates best practices for using the HackMD API client.
32+
933
## LICENSE
1034

1135
MIT

examples/nodejs/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
HACKMD_ACCESS_TOKEN=YOUR_ACCESS_TOKEN

examples/nodejs/README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# HackMD API Client Example
2+
3+
This is an example project demonstrating the usage of the HackMD API client.
4+
5+
## Setup
6+
7+
1. First, build the HackMD API package:
8+
```bash
9+
cd ../../nodejs
10+
npm install
11+
npm run build
12+
cd ../examples/nodejs
13+
```
14+
15+
2. Install the example dependencies:
16+
```bash
17+
npm install
18+
```
19+
20+
3. Set up your HackMD access token using one of these methods:
21+
22+
a. Set it as an environment variable:
23+
```bash
24+
# For Unix/Linux/macOS
25+
export HACKMD_ACCESS_TOKEN=your_access_token_here
26+
27+
# For Windows PowerShell
28+
$env:HACKMD_ACCESS_TOKEN="your_access_token_here"
29+
```
30+
31+
b. Or create a `.env` file in the project root (not tracked by git):
32+
```
33+
HACKMD_ACCESS_TOKEN=your_access_token_here
34+
```
35+
36+
You can get your access token from [HackMD API documentation](https://hackmd.io/@hackmd-api/developer-portal).
37+
38+
## Running the Example
39+
40+
To run the example:
41+
42+
```bash
43+
npm start
44+
```
45+
46+
## What's Demonstrated
47+
48+
The example demonstrates several features of the HackMD API client:
49+
50+
1. Getting user information
51+
2. Creating a new note
52+
3. Using ETag support for caching
53+
4. Updating note content
54+
5. Getting raw response data
55+
6. Deleting notes
56+
57+
## Features Shown
58+
59+
- Retry configuration with exponential backoff
60+
- ETag support for caching
61+
- Response data unwrapping
62+
- Error handling
63+
- Environment variable configuration

examples/nodejs/index.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import HackMDAPI from '@hackmd/api';
2+
import dotenv from 'dotenv';
3+
4+
// Load environment variables
5+
dotenv.config();
6+
7+
// Check for required environment variable
8+
if (!process.env.HACKMD_ACCESS_TOKEN) {
9+
console.error('Error: HACKMD_ACCESS_TOKEN environment variable is not set.');
10+
console.error('Please set your HackMD access token using one of these methods:');
11+
console.error('1. Create a .env file with HACKMD_ACCESS_TOKEN=your_token_here');
12+
console.error('2. Set the environment variable directly: export HACKMD_ACCESS_TOKEN=your_token_here');
13+
process.exit(1);
14+
}
15+
16+
// Create API client with retry configuration
17+
const client = new HackMDAPI(process.env.HACKMD_ACCESS_TOKEN, 'https://api.hackmd.io/v1', {
18+
retryConfig: {
19+
maxRetries: 3,
20+
baseDelay: 100
21+
}
22+
});
23+
24+
async function main() {
25+
try {
26+
// Example 1: Get user information
27+
console.log('Getting user information...');
28+
const me = await client.getMe();
29+
console.log('User email:', me.email);
30+
console.log('User name:', me.name);
31+
32+
// Example 2: Create a new note
33+
console.log('\nCreating a new note...');
34+
const newNote = await client.createNote({
35+
title: 'Test Note',
36+
content: '# Hello from HackMD API\n\nThis is a test note created using the API client.',
37+
readPermission: 'guest',
38+
writePermission: 'owner'
39+
});
40+
console.log('Created note ID:', newNote.id);
41+
console.log('Note URL:', newNote.publishLink);
42+
43+
// Example 3: Get note with ETag support
44+
console.log('\nGetting note with ETag support...');
45+
const note = await client.getNote(newNote.id);
46+
console.log('Note content:', note.content);
47+
48+
// Second request with ETag
49+
const updatedNote = await client.getNote(newNote.id, { etag: note.etag });
50+
console.log('Note status:', updatedNote.status);
51+
52+
// Example 4: Update note content
53+
console.log('\nUpdating note content...');
54+
const updatedContent = await client.updateNoteContent(newNote.id, '# Updated Content\n\nThis note has been updated!');
55+
console.log('Updated note content:', updatedContent.content);
56+
57+
// Example 5: Get raw response (unwrapData: false)
58+
console.log('\nGetting raw response...');
59+
const rawResponse = await client.getNote(newNote.id, { unwrapData: false });
60+
console.log('Response headers:', rawResponse.headers);
61+
console.log('Response status:', rawResponse.status);
62+
63+
// Example 6: Delete the test note
64+
console.log('\nCleaning up - deleting test note...');
65+
await client.deleteNote(newNote.id);
66+
console.log('Note deleted successfully');
67+
68+
} catch (error) {
69+
console.error('Error:', error.message);
70+
if (error.response) {
71+
console.error('Response status:', error.response.status);
72+
console.error('Response data:', error.response.data);
73+
}
74+
}
75+
}
76+
77+
main();

examples/nodejs/package-lock.json

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/nodejs/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "hackmd-api-example",
3+
"version": "1.0.0",
4+
"description": "Example usage of HackMD API client",
5+
"main": "index.js",
6+
"type": "module",
7+
"scripts": {
8+
"start": "node index.js"
9+
},
10+
"dependencies": {
11+
"@hackmd/api": "file:../../nodejs",
12+
"dotenv": "^16.4.5"
13+
}
14+
}

nodejs/.eslintrc.js renamed to nodejs/.eslintrc.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const config = {
2222
]
2323
},
2424
"ignorePatterns": [
25-
".eslintrc.js"
25+
".eslintrc.cjs"
2626
],
2727
}
2828

nodejs/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,101 @@ npm install @hackmd/api --save
2222

2323
## Example
2424

25+
### ES Modules (ESM)
26+
2527
```javascript
28+
// Default import
2629
import HackMDAPI from '@hackmd/api'
2730

31+
// Or named import
32+
import { API } from '@hackmd/api'
33+
2834
const client = new HackMDAPI('YOUR_ACCESS_TOKEN' /* required */, 'https://api.hackmd.io/v1' /* optional */)
2935

3036
client.getMe().then(me => {
3137
console.log(me.email)
3238
})
3339
```
3440

41+
### CommonJS
42+
43+
```javascript
44+
// Default import
45+
const HackMDAPI = require('@hackmd/api').default
46+
47+
// Or named import
48+
const { API } = require('@hackmd/api')
49+
50+
const client = new HackMDAPI('YOUR_ACCESS_TOKEN', 'https://api.hackmd.io/v1')
51+
52+
client.getMe().then(me => {
53+
console.log(me.email)
54+
})
55+
```
56+
57+
### Legacy Import Support
58+
59+
For backward compatibility, the package also supports legacy import paths:
60+
61+
```javascript
62+
// ESM
63+
import HackMDAPI from '@hackmd/api/dist'
64+
import { API } from '@hackmd/api/dist'
65+
66+
// CommonJS
67+
const HackMDAPI = require('@hackmd/api/dist').default
68+
const { API } = require('@hackmd/api/dist')
69+
70+
// Direct file imports
71+
import { API } from '@hackmd/api/dist/index.js'
72+
```
73+
74+
## Advanced Features
75+
76+
### Retry Configuration
77+
78+
The client supports automatic retry for failed requests with exponential backoff. You can configure retry behavior when creating the client:
79+
80+
```javascript
81+
const client = new HackMDAPI('YOUR_ACCESS_TOKEN', 'https://api.hackmd.io/v1', {
82+
retryConfig: {
83+
maxRetries: 3, // Maximum number of retry attempts
84+
baseDelay: 100 // Base delay in milliseconds for exponential backoff
85+
}
86+
})
87+
```
88+
89+
The client will automatically retry requests that fail with:
90+
- 5xx server errors
91+
- 429 Too Many Requests errors
92+
- Network errors
93+
94+
### Response Data Handling
95+
96+
By default, the client automatically unwraps the response data from the Axios response object. You can control this behavior using the `unwrapData` option:
97+
98+
```javascript
99+
// Get raw Axios response (includes headers, status, etc.)
100+
const response = await client.getMe({ unwrapData: false })
101+
102+
// Get only the data (default behavior)
103+
const data = await client.getMe({ unwrapData: true })
104+
```
105+
106+
### ETag Support
107+
108+
The client supports ETag-based caching for note retrieval. You can pass an ETag to check if the content has changed:
109+
110+
```javascript
111+
// First request
112+
const note = await client.getNote('note-id')
113+
const etag = note.etag
114+
115+
// Subsequent request with ETag
116+
const updatedNote = await client.getNote('note-id', { etag })
117+
// If the note hasn't changed, the response will have status 304
118+
```
119+
35120
## API
36121

37122
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.

0 commit comments

Comments
 (0)