@event-driven-io/emmett-fastify 0.43.0-beta.9 → 0.43.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,415 @@
1
+ # @event-driven-io/emmett-fastify
2
+
3
+ Fastify web framework integration for building event-sourced HTTP APIs with Emmett.
4
+
5
+ ## Purpose
6
+
7
+ This package provides seamless integration between the Emmett event sourcing library and Fastify, enabling you to build high-performance, event-sourced HTTP APIs. It includes sensible defaults for common plugins (ETag, compression, form body parsing) and automatic graceful shutdown handling.
8
+
9
+ ## Key Concepts
10
+
11
+ - **Application Factory**: Create pre-configured Fastify instances with essential plugins
12
+ - **Graceful Shutdown**: Automatic cleanup via `close-with-grace` when the server stops
13
+ - **Plugin System**: Extensible architecture using Fastify's plugin ecosystem
14
+ - **Decider Pattern**: Works seamlessly with Emmett's decider-based command handling
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @event-driven-io/emmett-fastify
20
+ ```
21
+
22
+ Since this package uses peer dependencies, you also need to install:
23
+
24
+ ```bash
25
+ npm install @event-driven-io/emmett fastify @fastify/compress @fastify/etag @fastify/formbody close-with-grace
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### Basic Application Setup
31
+
32
+ ```typescript
33
+ import { getApplication, startAPI } from '@event-driven-io/emmett-fastify';
34
+ import { getInMemoryEventStore } from '@event-driven-io/emmett';
35
+ import type { FastifyInstance } from 'fastify';
36
+
37
+ // Create your event store
38
+ const eventStore = getInMemoryEventStore();
39
+
40
+ // Define your routes
41
+ const registerRoutes = (app: FastifyInstance) => {
42
+ app.get('/health', async () => ({ status: 'ok' }));
43
+
44
+ app.post('/carts/:cartId/items', async (request, reply) => {
45
+ // Handle command with event store
46
+ return reply.code(201).send();
47
+ });
48
+ };
49
+
50
+ // Create and start the application
51
+ const app = await getApplication({ registerRoutes });
52
+ await startAPI(app, { port: 3000 });
53
+ ```
54
+
55
+ ### Shopping Cart API Example
56
+
57
+ Here is a complete example demonstrating the decider pattern with Fastify routes:
58
+
59
+ ```typescript
60
+ import {
61
+ DeciderCommandHandler,
62
+ getInMemoryEventStore,
63
+ type EventStore,
64
+ type Decider,
65
+ } from '@event-driven-io/emmett';
66
+ import { getApplication, startAPI } from '@event-driven-io/emmett-fastify';
67
+ import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
68
+
69
+ // Define events
70
+ type ShoppingCartEvent =
71
+ | {
72
+ type: 'ShoppingCartOpened';
73
+ data: { cartId: string; clientId: string; openedAt: Date };
74
+ }
75
+ | {
76
+ type: 'ProductItemAdded';
77
+ data: { cartId: string; productId: string; quantity: number };
78
+ }
79
+ | {
80
+ type: 'ShoppingCartConfirmed';
81
+ data: { cartId: string; confirmedAt: Date };
82
+ };
83
+
84
+ // Define commands
85
+ type ShoppingCartCommand =
86
+ | {
87
+ type: 'OpenShoppingCart';
88
+ data: { cartId: string; clientId: string; now: Date };
89
+ }
90
+ | {
91
+ type: 'AddProductItem';
92
+ data: { cartId: string; productId: string; quantity: number };
93
+ }
94
+ | { type: 'ConfirmShoppingCart'; data: { cartId: string; now: Date } };
95
+
96
+ // Define state
97
+ type ShoppingCart =
98
+ | { status: 'Empty' }
99
+ | {
100
+ status: 'Pending';
101
+ id: string;
102
+ clientId: string;
103
+ items: Array<{ productId: string; quantity: number }>;
104
+ }
105
+ | { status: 'Confirmed'; id: string; confirmedAt: Date };
106
+
107
+ // Implement the decider
108
+ const decider: Decider<ShoppingCart, ShoppingCartCommand, ShoppingCartEvent> = {
109
+ decide: (command, state) => {
110
+ switch (command.type) {
111
+ case 'OpenShoppingCart':
112
+ return {
113
+ type: 'ShoppingCartOpened',
114
+ data: {
115
+ cartId: command.data.cartId,
116
+ clientId: command.data.clientId,
117
+ openedAt: command.data.now,
118
+ },
119
+ };
120
+ case 'AddProductItem':
121
+ return {
122
+ type: 'ProductItemAdded',
123
+ data: {
124
+ cartId: command.data.cartId,
125
+ productId: command.data.productId,
126
+ quantity: command.data.quantity,
127
+ },
128
+ };
129
+ case 'ConfirmShoppingCart':
130
+ return {
131
+ type: 'ShoppingCartConfirmed',
132
+ data: { cartId: command.data.cartId, confirmedAt: command.data.now },
133
+ };
134
+ }
135
+ },
136
+ evolve: (state, event) => {
137
+ switch (event.type) {
138
+ case 'ShoppingCartOpened':
139
+ return {
140
+ status: 'Pending',
141
+ id: event.data.cartId,
142
+ clientId: event.data.clientId,
143
+ items: [],
144
+ };
145
+ case 'ProductItemAdded':
146
+ if (state.status !== 'Pending') return state;
147
+ return {
148
+ ...state,
149
+ items: [
150
+ ...state.items,
151
+ { productId: event.data.productId, quantity: event.data.quantity },
152
+ ],
153
+ };
154
+ case 'ShoppingCartConfirmed':
155
+ if (state.status !== 'Pending') return state;
156
+ return {
157
+ status: 'Confirmed',
158
+ id: state.id,
159
+ confirmedAt: event.data.confirmedAt,
160
+ };
161
+ }
162
+ },
163
+ initialState: () => ({ status: 'Empty' }),
164
+ };
165
+
166
+ // Create command handler
167
+ const handle = DeciderCommandHandler(decider);
168
+
169
+ // Register routes
170
+ const registerRoutes = (eventStore: EventStore) => (app: FastifyInstance) => {
171
+ app.post(
172
+ '/clients/:clientId/shopping-carts',
173
+ async (request: FastifyRequest, reply: FastifyReply) => {
174
+ const { clientId } = request.params as { clientId: string };
175
+ const cartId = clientId;
176
+
177
+ await handle(eventStore, cartId, {
178
+ type: 'OpenShoppingCart',
179
+ data: { cartId, clientId, now: new Date() },
180
+ });
181
+
182
+ return reply.code(201).send({ id: cartId });
183
+ },
184
+ );
185
+
186
+ app.post(
187
+ '/clients/:clientId/shopping-carts/:cartId/items',
188
+ async (request: FastifyRequest, reply: FastifyReply) => {
189
+ const { cartId } = request.params as { cartId: string };
190
+ const { productId, quantity } = request.body as {
191
+ productId: string;
192
+ quantity: number;
193
+ };
194
+
195
+ await handle(eventStore, cartId, {
196
+ type: 'AddProductItem',
197
+ data: { cartId, productId, quantity },
198
+ });
199
+
200
+ return reply.code(204).send();
201
+ },
202
+ );
203
+
204
+ app.post(
205
+ '/clients/:clientId/shopping-carts/:cartId/confirm',
206
+ async (request: FastifyRequest, reply: FastifyReply) => {
207
+ const { cartId } = request.params as { cartId: string };
208
+
209
+ await handle(eventStore, cartId, {
210
+ type: 'ConfirmShoppingCart',
211
+ data: { cartId, now: new Date() },
212
+ });
213
+
214
+ return reply.code(204).send();
215
+ },
216
+ );
217
+ };
218
+
219
+ // Start the server
220
+ const eventStore = getInMemoryEventStore();
221
+ const app = await getApplication({
222
+ registerRoutes: registerRoutes(eventStore),
223
+ });
224
+ await startAPI(app, { port: 3000 });
225
+ ```
226
+
227
+ ## How-to Guides
228
+
229
+ ### Custom Server Options
230
+
231
+ `serverOptions` takes Fastify's full server options. Fastify's logger is off by default, as in Fastify itself. Turn it on with `logger`, or pass your own logger with `loggerInstance`:
232
+
233
+ ```typescript
234
+ const app = await getApplication({
235
+ registerRoutes,
236
+ serverOptions: {
237
+ logger: true, // Enable Fastify logging
238
+ },
239
+ });
240
+ ```
241
+
242
+ ### Custom Plugins
243
+
244
+ Override or extend the default plugins:
245
+
246
+ ```typescript
247
+ import Cors from '@fastify/cors';
248
+
249
+ const app = await getApplication({
250
+ registerRoutes,
251
+ activeDefaultPlugins: [
252
+ { plugin: Cors, options: { origin: '*' } },
253
+ // Add your custom plugins here
254
+ ],
255
+ });
256
+ ```
257
+
258
+ ### Disable Default Plugins
259
+
260
+ Start with no default plugins:
261
+
262
+ ```typescript
263
+ const app = await getApplication({
264
+ registerRoutes,
265
+ activeDefaultPlugins: [],
266
+ });
267
+ ```
268
+
269
+ ### Testing with Fastify Inject
270
+
271
+ Use Fastify's built-in `inject` method for testing without starting a server:
272
+
273
+ ```typescript
274
+ import { getApplication } from '@event-driven-io/emmett-fastify';
275
+ import { getInMemoryEventStore } from '@event-driven-io/emmett';
276
+
277
+ const eventStore = getInMemoryEventStore();
278
+ const app = await getApplication({
279
+ registerRoutes: registerRoutes(eventStore),
280
+ });
281
+
282
+ // Test a route
283
+ const response = await app.inject({
284
+ method: 'POST',
285
+ url: '/clients/client-123/shopping-carts',
286
+ });
287
+
288
+ console.log(response.statusCode); // 201
289
+ console.log(response.json()); // { id: 'client-123' }
290
+ ```
291
+
292
+ ### Using with Different Event Stores
293
+
294
+ The package works with any Emmett event store implementation:
295
+
296
+ ```typescript
297
+ // With PostgreSQL
298
+ import { getPostgreSQLEventStore } from '@event-driven-io/emmett-postgresql';
299
+
300
+ const eventStore = getPostgreSQLEventStore(connectionPool);
301
+ const app = await getApplication({
302
+ registerRoutes: registerRoutes(eventStore),
303
+ });
304
+
305
+ // With EventStoreDB
306
+ import { getEventStoreDBEventStore } from '@event-driven-io/emmett-esdb';
307
+
308
+ const eventStore = getEventStoreDBEventStore(client);
309
+ const app = await getApplication({
310
+ registerRoutes: registerRoutes(eventStore),
311
+ });
312
+ ```
313
+
314
+ ## API Reference
315
+
316
+ ### `getApplication(options: ApplicationOptions): Promise<FastifyInstance>`
317
+
318
+ Creates a configured Fastify application instance.
319
+
320
+ **Parameters:**
321
+
322
+ | Option | Type | Default | Description |
323
+ | ---------------------- | -------------------------------- | ------------------------------------ | -------------------------------- |
324
+ | `registerRoutes` | `(app: FastifyInstance) => void` | `undefined` | Function to register your routes |
325
+ | `serverOptions` | `FastifyServerOptions` | Fastify's defaults (`logger: false`) | Fastify server configuration |
326
+ | `activeDefaultPlugins` | `Plugin[]` | `[ETag, Compress, FormBody]` | Plugins to register |
327
+
328
+ **Returns:** A Promise that resolves to a configured `FastifyInstance`.
329
+
330
+ ### `startAPI(app: FastifyInstance, options?: StartApiOptions): Promise<void>`
331
+
332
+ Starts the Fastify server.
333
+
334
+ **Parameters:**
335
+
336
+ | Option | Type | Default | Description |
337
+ | -------------- | ----------------- | -------- | -------------------------------- |
338
+ | `app` | `FastifyInstance` | required | The Fastify application instance |
339
+ | `options.port` | `number` | `5000` | Port number to listen on |
340
+
341
+ ### `ApplicationOptions`
342
+
343
+ ```typescript
344
+ interface ApplicationOptions {
345
+ serverOptions?: FastifyServerOptions;
346
+ registerRoutes?: (app: FastifyInstance) => void;
347
+ activeDefaultPlugins?: Plugin[];
348
+ observability?: Partial<Observability<string>>;
349
+ disableTraceIdHeader?: boolean;
350
+ }
351
+ ```
352
+
353
+ ### `StartApiOptions`
354
+
355
+ ```typescript
356
+ type StartApiOptions = {
357
+ port?: number;
358
+ };
359
+ ```
360
+
361
+ ### `Plugin`
362
+
363
+ ```typescript
364
+ type Plugin = {
365
+ plugin: FastifyPluginAsync | FastifyPluginCallback;
366
+ options: FastifyPluginOptions;
367
+ };
368
+ ```
369
+
370
+ ## Architecture
371
+
372
+ ### Default Plugins
373
+
374
+ The package registers these plugins by default:
375
+
376
+ | Plugin | Purpose |
377
+ | ------------------- | --------------------------------------------------- |
378
+ | `@fastify/etag` | Automatic ETag header generation for caching |
379
+ | `@fastify/compress` | Response compression (disabled globally by default) |
380
+ | `@fastify/formbody` | Form body parsing support |
381
+
382
+ ### Graceful Shutdown
383
+
384
+ The application automatically handles graceful shutdown using `close-with-grace`:
385
+
386
+ - Waits 500ms before forcing shutdown
387
+ - Logs any errors during shutdown
388
+ - Cleans up listeners when the application closes
389
+
390
+ ### Integration with Emmett Core
391
+
392
+ This package is designed to work with Emmett's core patterns:
393
+
394
+ ```
395
+ Fastify Route -> Command -> DeciderCommandHandler -> EventStore -> Events
396
+ ```
397
+
398
+ 1. HTTP requests arrive at Fastify routes
399
+ 2. Routes construct commands from request data
400
+ 3. `DeciderCommandHandler` processes commands using the decider pattern
401
+ 4. Events are appended to the event store
402
+ 5. Responses are sent back to the client
403
+
404
+ ## Dependencies
405
+
406
+ ### Peer Dependencies
407
+
408
+ | Package | Version | Purpose |
409
+ | ------------------------- | --------- | --------------------------- |
410
+ | `@event-driven-io/emmett` | `0.38.3` | Core event sourcing library |
411
+ | `fastify` | `^4.28.1` | Web framework |
412
+ | `@fastify/compress` | `^7.0.3` | Response compression |
413
+ | `@fastify/etag` | `^5.2.0` | ETag support |
414
+ | `@fastify/formbody` | `^7.4.0` | Form body parsing |
415
+ | `close-with-grace` | `^2.1.0` | Graceful shutdown |
package/dist/index.cjs CHANGED
@@ -1,56 +1,94 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts
2
- var _compress = require('@fastify/compress'); var _compress2 = _interopRequireDefault(_compress);
3
- var _etag = require('@fastify/etag'); var _etag2 = _interopRequireDefault(_etag);
4
- var _formbody = require('@fastify/formbody'); var _formbody2 = _interopRequireDefault(_formbody);
5
- var _closewithgrace = require('close-with-grace'); var _closewithgrace2 = _interopRequireDefault(_closewithgrace);
6
- var _fastify = require('fastify'); var _fastify2 = _interopRequireDefault(_fastify);
7
- var defaultPlugins = [
8
- { plugin: _etag2.default, options: {} },
9
- { plugin: _compress2.default, options: { global: false } },
10
- { plugin: _formbody2.default, options: {} }
11
- ];
12
- var getApplication = async (options) => {
13
- const {
14
- registerRoutes,
15
- activeDefaultPlugins = defaultPlugins,
16
- serverOptions = {
17
- logger: true
18
- }
19
- } = options;
20
- const app = _fastify2.default.call(void 0, serverOptions);
21
- await Promise.all(
22
- activeDefaultPlugins.map(async ({ plugin, options: options2 }) => {
23
- await app.register(plugin, options2);
24
- })
25
- );
26
- if (registerRoutes) {
27
- registerRoutes(app);
28
- }
29
- const closeListeners = _closewithgrace2.default.call(void 0, { delay: 500 }, async (opts) => {
30
- if (opts.err) {
31
- app.log.error(opts.err);
32
- }
33
- await app.close();
34
- });
35
- app.addHook("onClose", (instance, done) => {
36
- closeListeners.uninstall();
37
- done();
38
- });
39
- return app;
40
- };
41
- var startAPI = async (app, options = { port: 5e3 }) => {
42
- const { port } = options;
43
- try {
44
- await app.listen({ port });
45
- const address = app.server.address();
46
- console.log(`Server listening on ${_optionalChain([address, 'optionalAccess', _ => _.address])}:${_optionalChain([address, 'optionalAccess', _2 => _2.port])}`);
47
- } catch (err) {
48
- app.log.error(err);
49
- process.exit(1);
50
- }
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ // \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
51
22
  };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
52
27
 
28
+ let _fastify_compress = require("@fastify/compress");
29
+ _fastify_compress = __toESM(_fastify_compress, 1);
30
+ let _fastify_etag = require("@fastify/etag");
31
+ _fastify_etag = __toESM(_fastify_etag, 1);
32
+ let _fastify_formbody = require("@fastify/formbody");
33
+ _fastify_formbody = __toESM(_fastify_formbody, 1);
34
+ let _event_driven_io_emmett = require("@event-driven-io/emmett");
35
+ let close_with_grace = require("close-with-grace");
36
+ close_with_grace = __toESM(close_with_grace, 1);
37
+ let fastify = require("fastify");
38
+ fastify = __toESM(fastify, 1);
39
+ let _opentelemetry_api = require("@opentelemetry/api");
40
+
41
+ // src/traceIdHook.ts
42
+ const traceIdHook = (_request, reply, done) => {
43
+ const traceId = _opentelemetry_api.trace.getSpan(_opentelemetry_api.context.active())?.spanContext().traceId;
44
+ if (traceId) reply.header("x-trace-id", traceId);
45
+ done();
46
+ };
53
47
 
48
+ // src/index.ts
49
+ const defaultPlugins = [
50
+ {
51
+ plugin: _fastify_etag.default,
52
+ options: {}
53
+ },
54
+ {
55
+ plugin: _fastify_compress.default,
56
+ options: { global: false }
57
+ },
58
+ {
59
+ plugin: _fastify_formbody.default,
60
+ options: {}
61
+ }
62
+ ];
63
+ const getApplication = async (options) => {
64
+ const { registerRoutes, activeDefaultPlugins = defaultPlugins, serverOptions, observability, disableTraceIdHeader } = options;
65
+ const app = (0, fastify.default)(serverOptions);
66
+ if ((observability !== void 0 || (0, _event_driven_io_emmett.currentDefaultObservability)() !== void 0) && disableTraceIdHeader !== true) app.addHook("onRequest", traceIdHook);
67
+ await Promise.all(activeDefaultPlugins.map(async ({ plugin, options }) => {
68
+ await app.register(plugin, options);
69
+ }));
70
+ if (registerRoutes) registerRoutes(app);
71
+ const closeListeners = (0, close_with_grace.default)({ delay: 500 }, async (opts) => {
72
+ if (opts.err) app.log.error(opts.err);
73
+ await app.close();
74
+ });
75
+ app.addHook("onClose", (instance, done) => {
76
+ closeListeners.uninstall();
77
+ done();
78
+ });
79
+ return app;
80
+ };
81
+ const startAPI = async (app, options = { port: 5e3 }) => {
82
+ const { port } = options;
83
+ try {
84
+ await app.listen({ port });
85
+ } catch (err) {
86
+ app.log.error(err);
87
+ process.exit(1);
88
+ }
89
+ };
54
90
 
55
- exports.getApplication = getApplication; exports.startAPI = startAPI;
91
+ exports.getApplication = getApplication;
92
+ exports.startAPI = startAPI;
93
+ exports.traceIdHook = traceIdHook;
56
94
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett-fastify/dist/index.cjs","../src/index.ts"],"names":["options"],"mappings":"AAAA;ACAA,iGAAsD;AACtD,iFAA8C;AAC9C,iGAAkD;AAClD,kHAA2B;AAC3B,oFAKO;AAQP,IAAM,eAAA,EAA2B;AAAA,EAC/B,EAAE,MAAA,EAAQ,cAAA,EAAM,OAAA,EAAS,CAAC,EAAwB,CAAA;AAAA,EAClD,EAAE,MAAA,EAAQ,kBAAA,EAAU,OAAA,EAAS,EAAE,MAAA,EAAQ,MAAM,EAA4B,CAAA;AAAA,EACzE,EAAE,MAAA,EAAQ,kBAAA,EAAM,OAAA,EAAS,CAAC,EAA4B;AACxD,CAAA;AAQO,IAAM,eAAA,EAAiB,MAAA,CAAO,OAAA,EAAA,GAAgC;AACnE,EAAA,MAAM;AAAA,IACJ,cAAA;AAAA,IACA,qBAAA,EAAuB,cAAA;AAAA,IACvB,cAAA,EAAgB;AAAA,MACd,MAAA,EAAQ;AAAA,IACV;AAAA,EACF,EAAA,EAAI,OAAA;AAEJ,EAAA,MAAM,IAAA,EAAuB,+BAAA,aAAqB,CAAA;AAElD,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,oBAAA,CAAqB,GAAA,CAAI,MAAA,CAAO,EAAE,MAAA,EAAQ,OAAA,EAAAA,SAAQ,CAAA,EAAA,GAAM;AACtD,MAAA,MAAM,GAAA,CAAI,QAAA,CAAS,MAAA,EAAQA,QAAO,CAAA;AAAA,IACpC,CAAC;AAAA,EACH,CAAA;AAEA,EAAA,GAAA,CAAI,cAAA,EAAgB;AAClB,IAAA,cAAA,CAAe,GAAG,CAAA;AAAA,EACpB;AAEA,EAAA,MAAM,eAAA,EAAiB,sCAAA,EAAiB,KAAA,EAAO,IAAI,CAAA,EAAG,MAAA,CAAO,IAAA,EAAA,GAAS;AACpE,IAAA,GAAA,CAAI,IAAA,CAAK,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAAA,IACxB;AAEA,IAAA,MAAM,GAAA,CAAI,KAAA,CAAM,CAAA;AAAA,EAClB,CAAC,CAAA;AAED,EAAA,GAAA,CAAI,OAAA,CAAQ,SAAA,EAAW,CAAC,QAAA,EAAU,IAAA,EAAA,GAAS;AACzC,IAAA,cAAA,CAAe,SAAA,CAAU,CAAA;AACzB,IAAA,IAAA,CAAK,CAAA;AAAA,EACP,CAAC,CAAA;AAED,EAAA,OAAO,GAAA;AACT,CAAA;AAMO,IAAM,SAAA,EAAW,MAAA,CACtB,GAAA,EACA,QAAA,EAA2B,EAAE,IAAA,EAAM,IAAK,CAAA,EAAA,GACrC;AACH,EAAA,MAAM,EAAE,KAAK,EAAA,EAAI,OAAA;AACjB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,CAAI,MAAA,CAAO,EAAE,KAAK,CAAC,CAAA;AACzB,IAAA,MAAM,QAAA,EAAU,GAAA,CAAI,MAAA,CAAO,OAAA,CAAQ,CAAA;AAEnC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oBAAA,kBAAuB,OAAA,2BAAS,SAAO,CAAA,CAAA,kBAAI,OAAA,6BAAS,MAAI,CAAA,CAAA;AACxD,EAAA;AACK,IAAA;AACH,IAAA;AAChB,EAAA;AACF;ADjCyE;AACA;AACA;AACA","file":"/home/runner/work/emmett/emmett/src/packages/emmett-fastify/dist/index.cjs","sourcesContent":[null,"import Compress, { type FastifyCompressOptions } from '@fastify/compress';\nimport Etag, { type FastifyEtagOptions } from '@fastify/etag';\nimport Form, { type FastifyFormbodyOptions } from '@fastify/formbody';\nimport closeWithGrace from 'close-with-grace';\nimport Fastify, {\n type FastifyInstance,\n type FastifyPluginAsync,\n type FastifyPluginCallback,\n type FastifyPluginOptions,\n} from 'fastify';\n\n// TODO: THIS WILL NEED TO BE BETTER TYPED\ntype Plugin = {\n plugin: FastifyPluginAsync | FastifyPluginCallback;\n options: FastifyPluginOptions;\n};\n\nconst defaultPlugins: Plugin[] = [\n { plugin: Etag, options: {} as FastifyEtagOptions },\n { plugin: Compress, options: { global: false } as FastifyCompressOptions },\n { plugin: Form, options: {} as FastifyFormbodyOptions },\n];\n\nexport interface ApplicationOptions {\n serverOptions?: { logger: boolean };\n registerRoutes?: (app: FastifyInstance) => void;\n activeDefaultPlugins?: Plugin[];\n}\n\nexport const getApplication = async (options: ApplicationOptions) => {\n const {\n registerRoutes,\n activeDefaultPlugins = defaultPlugins,\n serverOptions = {\n logger: true,\n },\n } = options;\n\n const app: FastifyInstance = Fastify(serverOptions);\n\n await Promise.all(\n activeDefaultPlugins.map(async ({ plugin, options }) => {\n await app.register(plugin, options);\n }),\n );\n\n if (registerRoutes) {\n registerRoutes(app);\n }\n\n const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {\n if (opts.err) {\n app.log.error(opts.err);\n }\n\n await app.close();\n });\n\n app.addHook('onClose', (instance, done) => {\n closeListeners.uninstall();\n done();\n });\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = async (\n app: FastifyInstance,\n options: StartApiOptions = { port: 5000 },\n) => {\n const { port } = options;\n try {\n await app.listen({ port });\n const address = app.server.address() as { address: string; port: number };\n\n console.log(`Server listening on ${address?.address}:${address?.port}`);\n } catch (err) {\n app.log.error(err);\n process.exit(1);\n }\n};\n"]}
1
+ {"version":3,"file":"index.cjs","names":["trace","context","Etag","Compress","Form","Fastify","currentDefaultObservability","closeWithGrace"],"sources":["../src/traceIdHook.ts","../src/index.ts"],"sourcesContent":["import { context, trace } from '@opentelemetry/api';\nimport type { onRequestHookHandler } from 'fastify';\n\nexport const traceIdHook: onRequestHookHandler = (_request, reply, done) => {\n const traceId = trace.getSpan(context.active())?.spanContext().traceId;\n if (traceId) void reply.header('x-trace-id', traceId);\n done();\n};\n","import Compress from '@fastify/compress';\nimport Etag from '@fastify/etag';\nimport Form from '@fastify/formbody';\nimport {\n currentDefaultObservability,\n type Observability,\n} from '@event-driven-io/emmett';\nimport closeWithGrace from 'close-with-grace';\nimport Fastify, {\n type FastifyInstance,\n type FastifyPluginAsync,\n type FastifyPluginCallback,\n type FastifyPluginOptions,\n type FastifyServerOptions,\n} from 'fastify';\nimport { traceIdHook } from './traceIdHook';\n\nexport * from './traceIdHook';\n\n// TODO: THIS WILL NEED TO BE BETTER TYPED\ntype Plugin = {\n plugin: FastifyPluginAsync | FastifyPluginCallback;\n options: FastifyPluginOptions;\n};\n\nconst defaultPlugins: Plugin[] = [\n { plugin: Etag, options: {} },\n { plugin: Compress, options: { global: false } },\n { plugin: Form, options: {} },\n];\n\nexport interface ApplicationOptions {\n serverOptions?: FastifyServerOptions;\n registerRoutes?: (app: FastifyInstance) => void;\n activeDefaultPlugins?: Plugin[];\n observability?: Partial<Observability<string>>;\n disableTraceIdHeader?: boolean;\n}\n\nexport const getApplication = async (options: ApplicationOptions) => {\n const {\n registerRoutes,\n activeDefaultPlugins = defaultPlugins,\n serverOptions,\n observability,\n disableTraceIdHeader,\n } = options;\n\n const app: FastifyInstance = Fastify(serverOptions);\n\n const isObservabilityRegistered =\n observability !== undefined || currentDefaultObservability() !== undefined;\n\n if (isObservabilityRegistered && disableTraceIdHeader !== true)\n app.addHook('onRequest', traceIdHook);\n\n await Promise.all(\n activeDefaultPlugins.map(async ({ plugin, options }) => {\n await app.register(plugin, options);\n }),\n );\n\n if (registerRoutes) {\n registerRoutes(app);\n }\n\n const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {\n if (opts.err) {\n app.log.error(opts.err);\n }\n\n await app.close();\n });\n\n app.addHook('onClose', (instance, done) => {\n closeListeners.uninstall();\n done();\n });\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = async (\n app: FastifyInstance,\n options: StartApiOptions = { port: 5000 },\n) => {\n const { port } = options;\n try {\n await app.listen({ port });\n } catch (err) {\n app.log.error(err);\n process.exit(1);\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,MAAa,eAAqC,UAAU,OAAO,SAAS;CAC1E,MAAM,UAAUA,yBAAM,QAAQC,2BAAQ,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;CAC/D,IAAI,SAAS,AAAK,MAAM,OAAO,cAAc,OAAO;CACpD,KAAK;AACP;;;ACkBA,MAAM,iBAA2B;CAC/B;EAAE,QAAQC;EAAM,SAAS,CAAC;CAAE;CAC5B;EAAE,QAAQC;EAAU,SAAS,EAAE,QAAQ,MAAM;CAAE;CAC/C;EAAE,QAAQC;EAAM,SAAS,CAAC;CAAE;AAC9B;AAUA,MAAa,iBAAiB,OAAO,YAAgC;CACnE,MAAM,EACJ,gBACA,uBAAuB,gBACvB,eACA,eACA,yBACE;CAEJ,MAAM,UAAuBC,iBAAQ,aAAa;CAKlD,KAFE,kBAAkB,cAAaC,qDAA4B,MAAM,WAElC,yBAAyB,MACxD,IAAI,QAAQ,aAAa,WAAW;CAEtC,MAAM,QAAQ,IACZ,qBAAqB,IAAI,OAAO,EAAE,QAAQ,cAAc;EACtD,MAAM,IAAI,SAAS,QAAQ,OAAO;CACpC,CAAC,CACH;CAEA,IAAI,gBACF,eAAe,GAAG;CAGpB,MAAM,qBAAiBC,0BAAe,EAAE,OAAO,IAAI,GAAG,OAAO,SAAS;EACpE,IAAI,KAAK,KACP,IAAI,IAAI,MAAM,KAAK,GAAG;EAGxB,MAAM,IAAI,MAAM;CAClB,CAAC;CAED,IAAI,QAAQ,YAAY,UAAU,SAAS;EACzC,eAAe,UAAU;EACzB,KAAK;CACP,CAAC;CAED,OAAO;AACT;AAMA,MAAa,WAAW,OACtB,KACA,UAA2B,EAAE,MAAM,IAAK,MACrC;CACH,MAAM,EAAE,SAAS;CACjB,IAAI;EACF,MAAM,IAAI,OAAO,EAAE,KAAK,CAAC;CAC3B,SAAS,KAAK;EACZ,IAAI,IAAI,MAAM,GAAG;EACjB,QAAQ,KAAK,CAAC;CAChB;AACF"}
package/dist/index.d.cts CHANGED
@@ -1,22 +1,20 @@
1
- import * as node_http from 'node:http';
2
- import * as fastify from 'fastify';
3
- import { FastifyInstance, FastifyPluginAsync, FastifyPluginCallback, FastifyPluginOptions } from 'fastify';
4
-
1
+ import { Observability } from "@event-driven-io/emmett";
2
+ import { FastifyInstance, FastifyPluginAsync, FastifyPluginCallback, FastifyPluginOptions, FastifyServerOptions, onRequestHookHandler } from "fastify";
3
+ export declare const traceIdHook: onRequestHookHandler;
5
4
  type Plugin = {
6
- plugin: FastifyPluginAsync | FastifyPluginCallback;
7
- options: FastifyPluginOptions;
5
+ plugin: FastifyPluginAsync | FastifyPluginCallback;
6
+ options: FastifyPluginOptions;
8
7
  };
9
- interface ApplicationOptions {
10
- serverOptions?: {
11
- logger: boolean;
12
- };
13
- registerRoutes?: (app: FastifyInstance) => void;
14
- activeDefaultPlugins?: Plugin[];
8
+ export interface ApplicationOptions {
9
+ serverOptions?: FastifyServerOptions;
10
+ registerRoutes?: (app: FastifyInstance) => void;
11
+ activeDefaultPlugins?: Plugin[];
12
+ observability?: Partial<Observability<string>>;
13
+ disableTraceIdHeader?: boolean;
15
14
  }
16
- declare const getApplication: (options: ApplicationOptions) => Promise<FastifyInstance<fastify.RawServerDefault, node_http.IncomingMessage, node_http.ServerResponse<node_http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>>;
17
- type StartApiOptions = {
18
- port?: number;
15
+ export declare const getApplication: (options: ApplicationOptions) => Promise<FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>>;
16
+ export type StartApiOptions = {
17
+ port?: number;
19
18
  };
20
- declare const startAPI: (app: FastifyInstance, options?: StartApiOptions) => Promise<void>;
21
-
22
- export { type ApplicationOptions, type StartApiOptions, getApplication, startAPI };
19
+ export declare const startAPI: (app: FastifyInstance, options?: StartApiOptions) => Promise<void>;
20
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,22 +1,20 @@
1
- import * as node_http from 'node:http';
2
- import * as fastify from 'fastify';
3
- import { FastifyInstance, FastifyPluginAsync, FastifyPluginCallback, FastifyPluginOptions } from 'fastify';
4
-
1
+ import { Observability } from "@event-driven-io/emmett";
2
+ import { FastifyInstance, FastifyPluginAsync, FastifyPluginCallback, FastifyPluginOptions, FastifyServerOptions, onRequestHookHandler } from "fastify";
3
+ export declare const traceIdHook: onRequestHookHandler;
5
4
  type Plugin = {
6
- plugin: FastifyPluginAsync | FastifyPluginCallback;
7
- options: FastifyPluginOptions;
5
+ plugin: FastifyPluginAsync | FastifyPluginCallback;
6
+ options: FastifyPluginOptions;
8
7
  };
9
- interface ApplicationOptions {
10
- serverOptions?: {
11
- logger: boolean;
12
- };
13
- registerRoutes?: (app: FastifyInstance) => void;
14
- activeDefaultPlugins?: Plugin[];
8
+ export interface ApplicationOptions {
9
+ serverOptions?: FastifyServerOptions;
10
+ registerRoutes?: (app: FastifyInstance) => void;
11
+ activeDefaultPlugins?: Plugin[];
12
+ observability?: Partial<Observability<string>>;
13
+ disableTraceIdHeader?: boolean;
15
14
  }
16
- declare const getApplication: (options: ApplicationOptions) => Promise<FastifyInstance<fastify.RawServerDefault, node_http.IncomingMessage, node_http.ServerResponse<node_http.IncomingMessage>, fastify.FastifyBaseLogger, fastify.FastifyTypeProviderDefault>>;
17
- type StartApiOptions = {
18
- port?: number;
15
+ export declare const getApplication: (options: ApplicationOptions) => Promise<FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>>;
16
+ export type StartApiOptions = {
17
+ port?: number;
19
18
  };
20
- declare const startAPI: (app: FastifyInstance, options?: StartApiOptions) => Promise<void>;
21
-
22
- export { type ApplicationOptions, type StartApiOptions, getApplication, startAPI };
19
+ export declare const startAPI: (app: FastifyInstance, options?: StartApiOptions) => Promise<void>;
20
+ export {};
package/dist/index.js CHANGED
@@ -1,56 +1,60 @@
1
- // src/index.ts
2
1
  import Compress from "@fastify/compress";
3
2
  import Etag from "@fastify/etag";
4
3
  import Form from "@fastify/formbody";
4
+ import { currentDefaultObservability } from "@event-driven-io/emmett";
5
5
  import closeWithGrace from "close-with-grace";
6
6
  import Fastify from "fastify";
7
- var defaultPlugins = [
8
- { plugin: Etag, options: {} },
9
- { plugin: Compress, options: { global: false } },
10
- { plugin: Form, options: {} }
11
- ];
12
- var getApplication = async (options) => {
13
- const {
14
- registerRoutes,
15
- activeDefaultPlugins = defaultPlugins,
16
- serverOptions = {
17
- logger: true
18
- }
19
- } = options;
20
- const app = Fastify(serverOptions);
21
- await Promise.all(
22
- activeDefaultPlugins.map(async ({ plugin, options: options2 }) => {
23
- await app.register(plugin, options2);
24
- })
25
- );
26
- if (registerRoutes) {
27
- registerRoutes(app);
28
- }
29
- const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {
30
- if (opts.err) {
31
- app.log.error(opts.err);
32
- }
33
- await app.close();
34
- });
35
- app.addHook("onClose", (instance, done) => {
36
- closeListeners.uninstall();
37
- done();
38
- });
39
- return app;
7
+ import { context, trace } from "@opentelemetry/api";
8
+
9
+ // src/traceIdHook.ts
10
+ const traceIdHook = (_request, reply, done) => {
11
+ const traceId = trace.getSpan(context.active())?.spanContext().traceId;
12
+ if (traceId) reply.header("x-trace-id", traceId);
13
+ done();
40
14
  };
41
- var startAPI = async (app, options = { port: 5e3 }) => {
42
- const { port } = options;
43
- try {
44
- await app.listen({ port });
45
- const address = app.server.address();
46
- console.log(`Server listening on ${address?.address}:${address?.port}`);
47
- } catch (err) {
48
- app.log.error(err);
49
- process.exit(1);
50
- }
15
+
16
+ // src/index.ts
17
+ const defaultPlugins = [
18
+ {
19
+ plugin: Etag,
20
+ options: {}
21
+ },
22
+ {
23
+ plugin: Compress,
24
+ options: { global: false }
25
+ },
26
+ {
27
+ plugin: Form,
28
+ options: {}
29
+ }
30
+ ];
31
+ const getApplication = async (options) => {
32
+ const { registerRoutes, activeDefaultPlugins = defaultPlugins, serverOptions, observability, disableTraceIdHeader } = options;
33
+ const app = Fastify(serverOptions);
34
+ if ((observability !== void 0 || currentDefaultObservability() !== void 0) && disableTraceIdHeader !== true) app.addHook("onRequest", traceIdHook);
35
+ await Promise.all(activeDefaultPlugins.map(async ({ plugin, options }) => {
36
+ await app.register(plugin, options);
37
+ }));
38
+ if (registerRoutes) registerRoutes(app);
39
+ const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {
40
+ if (opts.err) app.log.error(opts.err);
41
+ await app.close();
42
+ });
43
+ app.addHook("onClose", (instance, done) => {
44
+ closeListeners.uninstall();
45
+ done();
46
+ });
47
+ return app;
51
48
  };
52
- export {
53
- getApplication,
54
- startAPI
49
+ const startAPI = async (app, options = { port: 5e3 }) => {
50
+ const { port } = options;
51
+ try {
52
+ await app.listen({ port });
53
+ } catch (err) {
54
+ app.log.error(err);
55
+ process.exit(1);
56
+ }
55
57
  };
58
+
59
+ export { getApplication, startAPI, traceIdHook };
56
60
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Compress, { type FastifyCompressOptions } from '@fastify/compress';\nimport Etag, { type FastifyEtagOptions } from '@fastify/etag';\nimport Form, { type FastifyFormbodyOptions } from '@fastify/formbody';\nimport closeWithGrace from 'close-with-grace';\nimport Fastify, {\n type FastifyInstance,\n type FastifyPluginAsync,\n type FastifyPluginCallback,\n type FastifyPluginOptions,\n} from 'fastify';\n\n// TODO: THIS WILL NEED TO BE BETTER TYPED\ntype Plugin = {\n plugin: FastifyPluginAsync | FastifyPluginCallback;\n options: FastifyPluginOptions;\n};\n\nconst defaultPlugins: Plugin[] = [\n { plugin: Etag, options: {} as FastifyEtagOptions },\n { plugin: Compress, options: { global: false } as FastifyCompressOptions },\n { plugin: Form, options: {} as FastifyFormbodyOptions },\n];\n\nexport interface ApplicationOptions {\n serverOptions?: { logger: boolean };\n registerRoutes?: (app: FastifyInstance) => void;\n activeDefaultPlugins?: Plugin[];\n}\n\nexport const getApplication = async (options: ApplicationOptions) => {\n const {\n registerRoutes,\n activeDefaultPlugins = defaultPlugins,\n serverOptions = {\n logger: true,\n },\n } = options;\n\n const app: FastifyInstance = Fastify(serverOptions);\n\n await Promise.all(\n activeDefaultPlugins.map(async ({ plugin, options }) => {\n await app.register(plugin, options);\n }),\n );\n\n if (registerRoutes) {\n registerRoutes(app);\n }\n\n const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {\n if (opts.err) {\n app.log.error(opts.err);\n }\n\n await app.close();\n });\n\n app.addHook('onClose', (instance, done) => {\n closeListeners.uninstall();\n done();\n });\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = async (\n app: FastifyInstance,\n options: StartApiOptions = { port: 5000 },\n) => {\n const { port } = options;\n try {\n await app.listen({ port });\n const address = app.server.address() as { address: string; port: number };\n\n console.log(`Server listening on ${address?.address}:${address?.port}`);\n } catch (err) {\n app.log.error(err);\n process.exit(1);\n }\n};\n"],"mappings":";AAAA,OAAO,cAA+C;AACtD,OAAO,UAAuC;AAC9C,OAAO,UAA2C;AAClD,OAAO,oBAAoB;AAC3B,OAAO,aAKA;AAQP,IAAM,iBAA2B;AAAA,EAC/B,EAAE,QAAQ,MAAM,SAAS,CAAC,EAAwB;AAAA,EAClD,EAAE,QAAQ,UAAU,SAAS,EAAE,QAAQ,MAAM,EAA4B;AAAA,EACzE,EAAE,QAAQ,MAAM,SAAS,CAAC,EAA4B;AACxD;AAQO,IAAM,iBAAiB,OAAO,YAAgC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,uBAAuB;AAAA,IACvB,gBAAgB;AAAA,MACd,QAAQ;AAAA,IACV;AAAA,EACF,IAAI;AAEJ,QAAM,MAAuB,QAAQ,aAAa;AAElD,QAAM,QAAQ;AAAA,IACZ,qBAAqB,IAAI,OAAO,EAAE,QAAQ,SAAAA,SAAQ,MAAM;AACtD,YAAM,IAAI,SAAS,QAAQA,QAAO;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,MAAI,gBAAgB;AAClB,mBAAe,GAAG;AAAA,EACpB;AAEA,QAAM,iBAAiB,eAAe,EAAE,OAAO,IAAI,GAAG,OAAO,SAAS;AACpE,QAAI,KAAK,KAAK;AACZ,UAAI,IAAI,MAAM,KAAK,GAAG;AAAA,IACxB;AAEA,UAAM,IAAI,MAAM;AAAA,EAClB,CAAC;AAED,MAAI,QAAQ,WAAW,CAAC,UAAU,SAAS;AACzC,mBAAe,UAAU;AACzB,SAAK;AAAA,EACP,CAAC;AAED,SAAO;AACT;AAMO,IAAM,WAAW,OACtB,KACA,UAA2B,EAAE,MAAM,IAAK,MACrC;AACH,QAAM,EAAE,KAAK,IAAI;AACjB,MAAI;AACF,UAAM,IAAI,OAAO,EAAE,KAAK,CAAC;AACzB,UAAM,UAAU,IAAI,OAAO,QAAQ;AAEnC,YAAQ,IAAI,uBAAuB,SAAS,OAAO,IAAI,SAAS,IAAI,EAAE;AAAA,EACxE,SAAS,KAAK;AACZ,QAAI,IAAI,MAAM,GAAG;AACjB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":["options"]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/traceIdHook.ts","../src/index.ts"],"sourcesContent":["import { context, trace } from '@opentelemetry/api';\nimport type { onRequestHookHandler } from 'fastify';\n\nexport const traceIdHook: onRequestHookHandler = (_request, reply, done) => {\n const traceId = trace.getSpan(context.active())?.spanContext().traceId;\n if (traceId) void reply.header('x-trace-id', traceId);\n done();\n};\n","import Compress from '@fastify/compress';\nimport Etag from '@fastify/etag';\nimport Form from '@fastify/formbody';\nimport {\n currentDefaultObservability,\n type Observability,\n} from '@event-driven-io/emmett';\nimport closeWithGrace from 'close-with-grace';\nimport Fastify, {\n type FastifyInstance,\n type FastifyPluginAsync,\n type FastifyPluginCallback,\n type FastifyPluginOptions,\n type FastifyServerOptions,\n} from 'fastify';\nimport { traceIdHook } from './traceIdHook';\n\nexport * from './traceIdHook';\n\n// TODO: THIS WILL NEED TO BE BETTER TYPED\ntype Plugin = {\n plugin: FastifyPluginAsync | FastifyPluginCallback;\n options: FastifyPluginOptions;\n};\n\nconst defaultPlugins: Plugin[] = [\n { plugin: Etag, options: {} },\n { plugin: Compress, options: { global: false } },\n { plugin: Form, options: {} },\n];\n\nexport interface ApplicationOptions {\n serverOptions?: FastifyServerOptions;\n registerRoutes?: (app: FastifyInstance) => void;\n activeDefaultPlugins?: Plugin[];\n observability?: Partial<Observability<string>>;\n disableTraceIdHeader?: boolean;\n}\n\nexport const getApplication = async (options: ApplicationOptions) => {\n const {\n registerRoutes,\n activeDefaultPlugins = defaultPlugins,\n serverOptions,\n observability,\n disableTraceIdHeader,\n } = options;\n\n const app: FastifyInstance = Fastify(serverOptions);\n\n const isObservabilityRegistered =\n observability !== undefined || currentDefaultObservability() !== undefined;\n\n if (isObservabilityRegistered && disableTraceIdHeader !== true)\n app.addHook('onRequest', traceIdHook);\n\n await Promise.all(\n activeDefaultPlugins.map(async ({ plugin, options }) => {\n await app.register(plugin, options);\n }),\n );\n\n if (registerRoutes) {\n registerRoutes(app);\n }\n\n const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => {\n if (opts.err) {\n app.log.error(opts.err);\n }\n\n await app.close();\n });\n\n app.addHook('onClose', (instance, done) => {\n closeListeners.uninstall();\n done();\n });\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = async (\n app: FastifyInstance,\n options: StartApiOptions = { port: 5000 },\n) => {\n const { port } = options;\n try {\n await app.listen({ port });\n } catch (err) {\n app.log.error(err);\n process.exit(1);\n }\n};\n"],"mappings":";;;;;;;;;AAGA,MAAa,eAAqC,UAAU,OAAO,SAAS;CAC1E,MAAM,UAAU,MAAM,QAAQ,QAAQ,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;CAC/D,IAAI,SAAS,AAAK,MAAM,OAAO,cAAc,OAAO;CACpD,KAAK;AACP;;;ACkBA,MAAM,iBAA2B;CAC/B;EAAE,QAAQ;EAAM,SAAS,CAAC;CAAE;CAC5B;EAAE,QAAQ;EAAU,SAAS,EAAE,QAAQ,MAAM;CAAE;CAC/C;EAAE,QAAQ;EAAM,SAAS,CAAC;CAAE;AAC9B;AAUA,MAAa,iBAAiB,OAAO,YAAgC;CACnE,MAAM,EACJ,gBACA,uBAAuB,gBACvB,eACA,eACA,yBACE;CAEJ,MAAM,MAAuB,QAAQ,aAAa;CAKlD,KAFE,kBAAkB,UAAa,4BAA4B,MAAM,WAElC,yBAAyB,MACxD,IAAI,QAAQ,aAAa,WAAW;CAEtC,MAAM,QAAQ,IACZ,qBAAqB,IAAI,OAAO,EAAE,QAAQ,cAAc;EACtD,MAAM,IAAI,SAAS,QAAQ,OAAO;CACpC,CAAC,CACH;CAEA,IAAI,gBACF,eAAe,GAAG;CAGpB,MAAM,iBAAiB,eAAe,EAAE,OAAO,IAAI,GAAG,OAAO,SAAS;EACpE,IAAI,KAAK,KACP,IAAI,IAAI,MAAM,KAAK,GAAG;EAGxB,MAAM,IAAI,MAAM;CAClB,CAAC;CAED,IAAI,QAAQ,YAAY,UAAU,SAAS;EACzC,eAAe,UAAU;EACzB,KAAK;CACP,CAAC;CAED,OAAO;AACT;AAMA,MAAa,WAAW,OACtB,KACA,UAA2B,EAAE,MAAM,IAAK,MACrC;CACH,MAAM,EAAE,SAAS;CACjB,IAAI;EACF,MAAM,IAAI,OAAO,EAAE,KAAK,CAAC;CAC3B,SAAS,KAAK;EACZ,IAAI,IAAI,MAAM,GAAG;EACjB,QAAQ,KAAK,CAAC;CAChB;AACF"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@event-driven-io/emmett-fastify",
3
- "version": "0.43.0-beta.9",
3
+ "version": "0.43.0-rc.1",
4
4
  "type": "module",
5
5
  "description": "Emmett - Event Sourcing development made simple",
6
6
  "scripts": {
7
- "build": "tsup",
7
+ "build": "tsdown",
8
8
  "build:ts": "tsc",
9
9
  "build:ts:watch": "tsc -b --watch",
10
10
  "test": "run-s test:unit test:int test:e2e",
@@ -50,14 +50,16 @@
50
50
  "files": [
51
51
  "dist"
52
52
  ],
53
- "dependencies": {},
53
+ "dependencies": {
54
+ "@fastify/compress": "^9.2.2",
55
+ "@fastify/etag": "^6.2.1",
56
+ "@fastify/formbody": "^9.0.1",
57
+ "close-with-grace": "^2.5.0"
58
+ },
54
59
  "devDependencies": {},
55
60
  "peerDependencies": {
56
- "@event-driven-io/emmett": "0.43.0-beta.9",
57
- "fastify": "^5.7.2",
58
- "@fastify/compress": "^8.3.1",
59
- "@fastify/etag": "^6.1.0",
60
- "@fastify/formbody": "^8.0.2",
61
- "close-with-grace": "^2.4.0"
61
+ "@event-driven-io/emmett": "0.43.0-rc.1",
62
+ "fastify": "^5.12.7",
63
+ "@opentelemetry/api": ">=1.10.0 <1.11.0"
62
64
  }
63
65
  }