Skip to content

Commit 3adee41

Browse files
authored
Merge pull request #257 from albe/copilot/v0x-move-to-node-module-api
Move to ES Modules (ESM)
2 parents 50d3642 + b526710 commit 3adee41

45 files changed

Lines changed: 649 additions & 2540 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ There is currently only a single other embedded event store for node/javascript:
3232
npm install event-storage
3333
```
3434

35-
## Quick Start
35+
> **CommonJS / `require()` users:** version 1.0 is ESM-only. If your project uses `require()` and migrating to ESM is not an option, install the 0.x series (`npm install event-storage@0`) which is functionally equivalent and retains full CJS support.
36+
37+
3638

3739
```javascript
38-
const EventStore = require('event-storage');
40+
import { EventStore } from 'event-storage';
3941

4042
const eventstore = new EventStore('my-event-store', { storageDirectory: './data' });
4143

docs/advanced.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ The test exits with code `0` if data loss is within bounds and code `1` otherwis
167167
To have the store self-repair on the next open, use `LOCK_RECLAIM`:
168168

169169
```javascript
170-
const EventStore = require('event-storage');
170+
import { EventStore, LOCK_RECLAIM } from 'event-storage';
171171

172172
const eventstore = new EventStore('my-event-store', {
173173
storageDirectory: './data',
174-
storageConfig: { lock: EventStore.LOCK_RECLAIM }
174+
storageConfig: { lock: LOCK_RECLAIM }
175175
});
176176

177177
eventstore.on('ready', () => {
@@ -184,7 +184,7 @@ For strict durability (no data loss at the cost of write throughput), combine th
184184
```javascript
185185
const eventstore = new EventStore('my-event-store', {
186186
storageConfig: {
187-
lock: EventStore.LOCK_RECLAIM,
187+
lock: LOCK_RECLAIM,
188188
syncOnFlush: true
189189
}
190190
});
@@ -225,7 +225,7 @@ const eventstore = new EventStore('my-event-store', {
225225
Replace the default JSON serializer with any `serialize`/`deserialize` pair:
226226

227227
```javascript
228-
const { encode, decode } = require('@msgpack/msgpack');
228+
import { encode, decode } from '@msgpack/msgpack';
229229

230230
const eventstore = new EventStore('my-event-store', {
231231
storageConfig: {
@@ -249,7 +249,7 @@ Use the `serializer` option to wrap events in a compression codec.
249249
### LZ4 Example
250250

251251
```javascript
252-
const lz4 = require('lz4');
252+
import lz4 from 'lz4';
253253

254254
const eventstore = new EventStore('my-event-store', {
255255
storageConfig: {
@@ -307,7 +307,7 @@ Both hooks run synchronously on every operation. Keep handler logic cheap — av
307307
### EventStore Level
308308

309309
```javascript
310-
const EventStore = require('event-storage');
310+
import { EventStore } from 'event-storage';
311311

312312
const globalContext = { authorizedRoles: ['user'] };
313313

@@ -347,7 +347,7 @@ Use `eventstore.preCommit(handler)` / `eventstore.preRead(handler)` as convenien
347347
If you use the `Storage` class directly:
348348

349349
```javascript
350-
const Storage = require('event-storage').Storage;
350+
import { Storage } from 'event-storage';
351351

352352
const storage = new Storage('events', {
353353
partitioner: (doc) => doc.stream,

docs/api.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ This page lists all constructors and public methods of the three main classes.
1414
`EventStore` is the main entry point of the library.
1515

1616
```javascript
17-
const EventStore = require('event-storage');
18-
// or
19-
const { EventStore } = require('event-storage');
17+
import { EventStore } from 'event-storage';
2018
```
2119

2220
`EventStore` extends Node's `EventEmitter`. After construction it emits a
@@ -290,7 +288,7 @@ Asynchronously scan all consumer state files and return their identifiers.
290288
`EventStream` is returned by `EventStore.getEventStream()` and related methods.
291289

292290
```javascript
293-
const { EventStream } = require('event-storage');
291+
import { EventStream } from 'event-storage';
294292
```
295293

296294
`EventStream` extends Node's `stream.Readable` (in `objectMode`).
@@ -496,10 +494,10 @@ Return the next event object from the iterator, or `false` when the stream is ex
496494

497495
## Storage
498496

499-
`Storage` (exported as `require('event-storage').Storage`) is the low-level append-only document store used internally by `EventStore`. It can be used directly for advanced use cases.
497+
`Storage` is the low-level append-only document store used internally by `EventStore`. It can be used directly for advanced use cases.
500498

501499
```javascript
502-
const { Storage } = require('event-storage');
500+
import { Storage } from 'event-storage';
503501

504502
// Writable storage (default export)
505503
const store = new Storage('mystore', { dataDirectory: './data' });

docs/consumers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ How this works:
124124
Open the store in read-only mode to create consumers that run in a **separate process** from the writer:
125125
126126
```javascript
127-
const EventStore = require('event-storage');
127+
import { EventStore } from 'event-storage';
128128

129129
const eventstore = new EventStore('my-event-store', {
130130
storageDirectory: './data',

docs/getting-started.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ Install the package from npm:
88
npm install event-storage
99
```
1010

11-
## Quick Start
11+
!!! note "CommonJS users"
12+
Version 1.0 is ESM-only (`import` syntax). If your project uses `require()` and migrating to ESM is not currently an option, the **0.x series** is functionally equivalent and retains full CJS support:
13+
14+
```bash
15+
npm install event-storage@0
16+
```
17+
18+
1219

1320
```javascript
14-
const EventStore = require('event-storage');
21+
import { EventStore } from 'event-storage';
1522

1623
const eventstore = new EventStore('my-event-store', { storageDirectory: './data' });
1724

@@ -63,11 +70,11 @@ eventstore.commit('orders', [{ type: 'OrderShipped', orderId: 42 }], 3, (err) =>
6370

6471
The `expectedVersion` can be:
6572

66-
- `EventStore.ExpectedVersion.Any` (`-1`) — no check (the default).
67-
- `EventStore.ExpectedVersion.EmptyStream` (`0`) — only succeeds when the stream has no events yet.
73+
- `ExpectedVersion.Any` (`-1`) — no check (the default).
74+
- `ExpectedVersion.EmptyStream` (`0`) — only succeeds when the stream has no events yet.
6875
- Any positive integer — the stream must currently be at exactly that version.
6976

70-
An `EventStore.OptimisticConcurrencyError` is thrown when the stream version does not match. See [Optimistic Concurrency](streams.md#optimistic-concurrency) for more details.
77+
An `OptimisticConcurrencyError` is thrown when the stream version does not match. See [Optimistic Concurrency](streams.md#optimistic-concurrency) for more details.
7178

7279
## Reading Events
7380

docs/upgrading.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Upgrading from 0.x to 1.0
2+
3+
Version 1.0 migrates the entire library to native **ES Modules (ESM)**. If your application was using `require('event-storage')` you will need to update your import statements and a few API references.
4+
5+
---
6+
7+
## 1. Node.js version
8+
9+
ESM support requires **Node.js 18 or later**. Check your version:
10+
11+
```bash
12+
node --version
13+
```
14+
15+
---
16+
17+
## 2. Update your `package.json`
18+
19+
Your own project must opt in to ESM. Add `"type": "module"` to your `package.json`:
20+
21+
```json
22+
{
23+
"type": "module"
24+
}
25+
```
26+
27+
If you cannot migrate your whole project to ESM, you can rename individual files from `.js` to `.mjs` — Node.js treats `.mjs` files as ESM regardless of the `"type"` field.
28+
29+
---
30+
31+
## 3. Replace `require()` with `import`
32+
33+
### Basic import
34+
35+
```js
36+
// Before (0.x)
37+
const EventStore = require('event-storage');
38+
39+
// After (1.0)
40+
import { EventStore } from 'event-storage';
41+
```
42+
43+
### Named exports that were previously properties
44+
45+
In 0.x, constants and sub-classes were attached as properties on the default export. Constants are now individual named exports, while sub-classes remain accessible as properties of the parent class:
46+
47+
| 0.x | 1.0 |
48+
|-----|-----|
49+
| `EventStore.ExpectedVersion` | `import { ExpectedVersion } from 'event-storage'` |
50+
| `EventStore.OptimisticConcurrencyError` | `import { OptimisticConcurrencyError } from 'event-storage'` |
51+
| `EventStore.LOCK_THROW` | `import { LOCK_THROW } from 'event-storage'` |
52+
| `EventStore.LOCK_RECLAIM` | `import { LOCK_RECLAIM } from 'event-storage'` |
53+
| `require('event-storage').Storage` | `import { Storage } from 'event-storage'` |
54+
| `Storage.ReadOnly` | `Storage.ReadOnly` (unchanged — still a property of `Storage`) |
55+
| `Storage.StorageLockedError` | `import { StorageLockedError } from 'event-storage'` |
56+
| `Index.ReadOnly` | `Index.ReadOnly` (unchanged — still a property of `Index`) |
57+
| `Index.Entry` | `Index.Entry` (unchanged — still a property of `Index`) |
58+
59+
### Full import surface
60+
61+
All public exports from the package entry point:
62+
63+
```js
64+
import {
65+
EventStore, ExpectedVersion, OptimisticConcurrencyError,
66+
EventStream,
67+
Storage, StorageLockedError,
68+
Index,
69+
Consumer,
70+
LOCK_THROW, LOCK_RECLAIM
71+
} from 'event-storage';
72+
```
73+
74+
---
75+
76+
## 4. Common patterns updated
77+
78+
### Creating an event store
79+
80+
```js
81+
// Before
82+
const EventStore = require('event-storage');
83+
const eventstore = new EventStore('my-store', { storageDirectory: './data' });
84+
85+
// After
86+
import { EventStore } from 'event-storage';
87+
const eventstore = new EventStore('my-store', { storageDirectory: './data' });
88+
```
89+
90+
### Optimistic concurrency
91+
92+
```js
93+
// Before
94+
eventstore.commit('my-stream', events, EventStore.ExpectedVersion.EmptyStream, callback);
95+
// …and catching errors:
96+
if (err instanceof EventStore.OptimisticConcurrencyError) { … }
97+
98+
// After
99+
import { EventStore, ExpectedVersion, OptimisticConcurrencyError } from 'event-storage';
100+
eventstore.commit('my-stream', events, ExpectedVersion.EmptyStream, callback);
101+
if (err instanceof OptimisticConcurrencyError) { … }
102+
```
103+
104+
### Lock modes
105+
106+
```js
107+
// Before
108+
const EventStore = require('event-storage');
109+
const eventstore = new EventStore('my-store', {
110+
storageConfig: { lock: EventStore.LOCK_RECLAIM }
111+
});
112+
113+
// After
114+
import { EventStore, LOCK_RECLAIM } from 'event-storage';
115+
const eventstore = new EventStore('my-store', {
116+
storageConfig: { lock: LOCK_RECLAIM }
117+
});
118+
```
119+
120+
### Using the Storage class directly
121+
122+
```js
123+
// Before
124+
const Storage = require('event-storage').Storage;
125+
const ReadOnlyStorage = Storage.ReadOnly;
126+
const store = new ReadOnlyStorage('mystore', { dataDirectory: './data' });
127+
128+
// After
129+
import { Storage } from 'event-storage';
130+
const store = new Storage.ReadOnly('mystore', { dataDirectory: './data' });
131+
```
132+
133+
### Custom serialization / compression
134+
135+
```js
136+
// Before
137+
const { encode, decode } = require('@msgpack/msgpack');
138+
139+
// After
140+
import { encode, decode } from '@msgpack/msgpack';
141+
```
142+
143+
---
144+
145+
## 5. Relative file imports require `.js` extensions
146+
147+
If your project imports internal modules from `node_modules/event-storage` by path (uncommon), note that ESM requires explicit file extensions. This change is internal to the library and should not affect application code that imports from `'event-storage'`.
148+
149+
---
150+
151+
## 6. `__dirname` / `__filename`
152+
153+
These globals are not available in ESM. If you reference them in your own application code, replace them with:
154+
155+
```js
156+
import { fileURLToPath } from 'url';
157+
import path from 'path';
158+
159+
const __filename = fileURLToPath(import.meta.url);
160+
const __dirname = path.dirname(__filename);
161+
```
162+
163+
---
164+
165+
## 7. Dynamic `require()` / `createRequire`
166+
167+
If you have tooling or test helpers that still need CJS-style loading, use `createRequire`:
168+
169+
```js
170+
import { createRequire } from 'module';
171+
const require = createRequire(import.meta.url);
172+
```
173+
174+
This is a compatibility shim and is generally not needed when consuming `event-storage` itself.

index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
module.exports = require('./src/EventStore');
2-
module.exports.EventStore = module.exports;
3-
module.exports.EventStream = require('./src/EventStream');
4-
module.exports.Storage = require('./src/Storage');
5-
module.exports.Index = require('./src/Index');
6-
module.exports.Consumer = require('./src/Consumer');
1+
export { default as EventStore, ExpectedVersion, OptimisticConcurrencyError, LOCK_THROW, LOCK_RECLAIM } from './src/EventStore.js';
2+
export { default as EventStream } from './src/EventStream.js';
3+
export { default as Storage, StorageLockedError } from './src/Storage.js';
4+
export { default as Index } from './src/Index.js';
5+
export { default as Consumer } from './src/Consumer.js';

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ nav:
1717
- Event Streams: streams.md
1818
- Consumers: consumers.md
1919
- Advanced Topics: advanced.md
20-
- Implementation Architecture: architecture.md
2120
- API Reference: api.md
21+
- Implementation Architecture: architecture.md
22+
- Upgrading from 0.x to 1.0: upgrading.md

0 commit comments

Comments
 (0)