or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser.mdcore.mdindex.mdnode.md

node.mddocs/

0

# Node.js File Storage

1

2

File-based storage adapters and convenience presets for Node.js environments. These adapters support JSON files, plain text files, and custom data formats with atomic write operations for data safety.

3

4

## Capabilities

5

6

### JSON File Presets

7

8

Pre-configured database instances with JSON file adapters for immediate use.

9

10

```typescript { .api }

11

/**

12

* Create a Low instance with JSONFile adapter, automatically switches to Memory adapter during tests

13

* @param filename - Path to the JSON file

14

* @param defaultData - Default data structure

15

* @returns Promise resolving to configured Low instance with data pre-loaded

16

*/

17

function JSONFilePreset<Data>(filename: PathLike, defaultData: Data): Promise<Low<Data>>;

18

19

/**

20

* Create a LowSync instance with JSONFileSync adapter, automatically switches to MemorySync adapter during tests

21

* @param filename - Path to the JSON file

22

* @param defaultData - Default data structure

23

* @returns Configured LowSync instance with data pre-loaded

24

*/

25

function JSONFileSyncPreset<Data>(filename: PathLike, defaultData: Data): LowSync<Data>;

26

```

27

28

**Usage Examples:**

29

30

```typescript

31

import { JSONFilePreset, JSONFileSyncPreset } from "lowdb/node";

32

33

// Async preset

34

type Data = { posts: Array<{ id: number; title: string }> };

35

const defaultData: Data = { posts: [] };

36

37

const db = await JSONFilePreset("db.json", defaultData);

38

await db.update(({ posts }) => posts.push({ id: 1, title: "Hello World" }));

39

40

// Sync preset

41

const syncDb = JSONFileSyncPreset("sync-db.json", { settings: {} });

42

syncDb.update((data) => {

43

data.settings.theme = "dark";

44

});

45

```

46

47

### JSON File Adapters

48

49

Direct JSON file adapters with automatic parsing and formatting.

50

51

```typescript { .api }

52

/**

53

* Async JSON file adapter with automatic JSON parsing/stringifying

54

* @template T - The type of data stored in the JSON file

55

*/

56

class JSONFile<T> implements Adapter<T> {

57

constructor(filename: PathLike);

58

59

/** Read and parse JSON file content, returns null if file doesn't exist */

60

read(): Promise<T | null>;

61

62

/** Stringify and write data to JSON file with atomic write operation */

63

write(obj: T): Promise<void>;

64

}

65

66

/**

67

* Sync JSON file adapter with automatic JSON parsing/stringifying

68

* @template T - The type of data stored in the JSON file

69

*/

70

class JSONFileSync<T> implements SyncAdapter<T> {

71

constructor(filename: PathLike);

72

73

/** Read and parse JSON file content synchronously, returns null if file doesn't exist */

74

read(): T | null;

75

76

/** Stringify and write data to JSON file synchronously with atomic write operation */

77

write(obj: T): void;

78

}

79

```

80

81

**Usage Examples:**

82

83

```typescript

84

import { Low, LowSync } from "lowdb";

85

import { JSONFile, JSONFileSync } from "lowdb/node";

86

87

// Async JSON file adapter

88

const adapter = new JSONFile("data.json");

89

const db = new Low(adapter, { users: [] });

90

await db.read();

91

db.data.users.push({ id: 1, name: "Alice" });

92

await db.write();

93

94

// Sync JSON file adapter

95

const syncAdapter = new JSONFileSync("config.json");

96

const syncDb = new LowSync(syncAdapter, { theme: "light" });

97

syncDb.read();

98

syncDb.data.theme = "dark";

99

syncDb.write();

100

```

101

102

### Text File Adapters

103

104

Raw text file adapters for custom data formats and plain text storage.

105

106

```typescript { .api }

107

/**

108

* Async text file adapter using steno for atomic writes

109

*/

110

class TextFile implements Adapter<string> {

111

constructor(filename: PathLike);

112

113

/** Read text file content, returns null if file doesn't exist */

114

read(): Promise<string | null>;

115

116

/** Write text to file with atomic write operation using steno */

117

write(str: string): Promise<void>;

118

}

119

120

/**

121

* Sync text file adapter with atomic writes using temporary files

122

*/

123

class TextFileSync implements SyncAdapter<string> {

124

constructor(filename: PathLike);

125

126

/** Read text file content synchronously, returns null if file doesn't exist */

127

read(): string | null;

128

129

/** Write text to file synchronously with atomic write using temporary file */

130

write(str: string): void;

131

}

132

```

133

134

**Usage Examples:**

135

136

```typescript

137

import { Low, LowSync } from "lowdb";

138

import { TextFile, TextFileSync } from "lowdb/node";

139

140

// Async text file adapter

141

const textAdapter = new TextFile("log.txt");

142

const logDb = new Low(textAdapter, "");

143

await logDb.read();

144

await logDb.update((data) => data + "New log entry\n");

145

146

// Sync text file adapter

147

const syncTextAdapter = new TextFileSync("notes.txt");

148

const notesDb = new LowSync(syncTextAdapter, "");

149

notesDb.read();

150

notesDb.data += "Important note\n";

151

notesDb.write();

152

```

153

154

### Data File Adapters

155

156

Flexible adapters for custom data formats with configurable parse and stringify functions.

157

158

```typescript { .api }

159

/**

160

* Async data file adapter with custom parse/stringify functions

161

* @template T - The type of data stored

162

*/

163

class DataFile<T> implements Adapter<T> {

164

constructor(

165

filename: PathLike,

166

options: {

167

parse: (str: string) => T;

168

stringify: (data: T) => string;

169

}

170

);

171

172

/** Read file content and parse using custom parse function */

173

read(): Promise<T | null>;

174

175

/** Stringify data using custom stringify function and write to file */

176

write(obj: T): Promise<void>;

177

}

178

179

/**

180

* Sync data file adapter with custom parse/stringify functions

181

* @template T - The type of data stored

182

*/

183

class DataFileSync<T> implements SyncAdapter<T> {

184

constructor(

185

filename: PathLike,

186

options: {

187

parse: (str: string) => T;

188

stringify: (data: T) => string;

189

}

190

);

191

192

/** Read file content and parse using custom parse function synchronously */

193

read(): T | null;

194

195

/** Stringify data using custom stringify function and write to file synchronously */

196

write(obj: T): void;

197

}

198

```

199

200

**Usage Examples:**

201

202

```typescript

203

import { Low } from "lowdb";

204

import { DataFile } from "lowdb/node";

205

import YAML from "yaml";

206

207

// YAML file adapter

208

const yamlAdapter = new DataFile("config.yaml", {

209

parse: YAML.parse,

210

stringify: YAML.stringify

211

});

212

213

const yamlDb = new Low(yamlAdapter, { servers: [] });

214

await yamlDb.read();

215

216

// CSV file adapter with custom parsing

217

const csvAdapter = new DataFile("data.csv", {

218

parse: (str) => str.split('\n').map(line => line.split(',')),

219

stringify: (data) => data.map(row => row.join(',')).join('\n')

220

});

221

222

// Encrypted JSON adapter

223

const encryptedAdapter = new DataFile("secret.json", {

224

parse: (str) => JSON.parse(decrypt(str)),

225

stringify: (data) => encrypt(JSON.stringify(data))

226

});

227

```

228

229

## File System Behavior

230

231

### Atomic Writes

232

233

All file adapters use atomic write operations to prevent data corruption:

234

235

- **TextFile**: Uses the `steno` library for atomic writes with temporary files

236

- **TextFileSync**: Creates temporary files and uses `fs.renameSync` for atomic operations

237

- **JSONFile/JSONFileSync**: Inherit atomic behavior from TextFile adapters

238

- **DataFile/DataFileSync**: Inherit atomic behavior from TextFile adapters

239

240

### File Not Found Handling

241

242

When a file doesn't exist:

243

244

```typescript

245

const db = await JSONFilePreset("nonexistent.json", { count: 0 });

246

// db.data will be { count: 0 } (default data)

247

248

await db.read(); // No error thrown, uses default data

249

// db.data remains { count: 0 }

250

251

await db.write(); // Creates the file with current data

252

```

253

254

### Directory Creation

255

256

File adapters do not automatically create parent directories. Ensure directories exist:

257

258

```typescript

259

import { mkdir } from "fs/promises";

260

import { JSONFilePreset } from "lowdb/node";

261

262

// Create directory if needed

263

await mkdir("data", { recursive: true });

264

const db = await JSONFilePreset("data/app.json", {});

265

```

266

267

## Test Environment Behavior

268

269

Presets automatically switch to memory adapters when `NODE_ENV=test`:

270

271

```typescript

272

// In test environment (NODE_ENV=test)

273

const db = await JSONFilePreset("db.json", { posts: [] });

274

// Uses Memory adapter instead of JSONFile

275

// No actual file I/O occurs during testing

276

277

// In production environment

278

const db = await JSONFilePreset("db.json", { posts: [] });

279

// Uses JSONFile adapter for actual file persistence

280

```

281

282

## Error Handling

283

284

File adapters may throw various Node.js file system errors:

285

286

```typescript

287

import { JSONFilePreset } from "lowdb/node";

288

289

try {

290

const db = await JSONFilePreset("/readonly/db.json", {});

291

await db.write();

292

} catch (error) {

293

if (error.code === "EACCES") {

294

console.error("Permission denied");

295

} else if (error.code === "ENOENT") {

296

console.error("Directory doesn't exist");

297

} else if (error.code === "ENOSPC") {

298

console.error("No space left on device");

299

}

300

}

301

302

// Handle JSON parsing errors

303

try {

304

const db = await JSONFilePreset("malformed.json", {});

305

await db.read();

306

} catch (error) {

307

if (error instanceof SyntaxError) {

308

console.error("Invalid JSON format");

309

}

310

}

311

```

312

313

## Performance Considerations

314

315

### Sync vs Async

316

317

- **Async adapters**: Non-blocking I/O, suitable for servers and applications with concurrent operations

318

- **Sync adapters**: Blocking I/O, suitable for CLI tools and simple scripts

319

320

### File Size

321

322

lowdb loads the entire file into memory. For large datasets (>100MB), consider:

323

324

- Splitting data across multiple files

325

- Using streaming database solutions

326

- Implementing custom adapters with partial loading

327

328

### Write Frequency

329

330

Atomic writes create temporary files. For high-frequency writes:

331

332

- Batch updates using the `update()` method

333

- Consider using Memory adapters with periodic persistence

334

- Implement custom adapters with write buffering

335

336

## Types

337

338

```typescript { .api }

339

/** Node.js path-like type (string, Buffer, or URL) */

340

type PathLike = string | Buffer | URL;

341

```